簡體   English   中英

沒有返回值和一個允許子類型類的參數的C#委托(作為參數)

[英]C# delegate for function with no return value and one parameter that allows sub type classes (as parameter)

我正在尋找一個封裝了不返回任何值並采用一個參數的方法的委托,就像Action <T>一樣,但是不幸的是,委托與以子類型作為參數的方法不匹配...

那就是我想要做的:

public class BaseType
{
    public BaseType()
    {

    }
}
public class ChildType : BaseType
{
    public ChildType()
    {

    }
}
public class Test
{

public delegate void CallBackHandler(BaseType p);

    public Test()
    {
        CallBackHandler clbk1 = callBackA;
        CallBackHandler clbk2 = callBackB;   //That line does not compile
                                             //->'No overload for 'callBackB' matches delegate 'Test.CallBackHandler'
    }

    private void callBackA(BaseType p)
    {

    }

    private void callBackB(ChildType p)
    {

    }
}

我讀到有關協方差,逆方差等的信息。我知道它處理繼承的類型轉換,但是我對所有這些都有些困惑...

我應該使用哪個委托來使代碼正常工作?

您不可以這樣做,因為它不安全。 如果允許,您可以執行以下操作:

class OtherChild : BaseType { }

CallBackHandler clbk2 = callBackB;
clbk2(new OtherChild());

並將OtherChild的實例OtherChild給需要ChildType實例的ChildType 請注意,以下內容是安全的並且可以編譯:

public delegate void CallBackHandler(ChildType p);

CallBackHandler clbk1 = callBackA;
CallBackHandler clbk2 = callBackB;

將代表聲明為

public delegate void CallBackHandler(ChildType p)

如果處理程序可以接受並且應該對BaseType實例采取行動,那么如果您傳入新類NewChildType的實例,將會發生什么? 沒人知道,這就是為什么你不能在這里。

這是創建強類型化來解決的經典類型安全性問題。

這是一個例子

abstract class Vehicle
{
    public virtual void MethodSlot1_StartEngine() { }

    public virtual void MethodSlot2_StopEngine() { }
}

class Car : Vehicle
{
    public virtual void MethodSlot3_OpenGasTank() { }
}

class NuclearSubmarine : Vehicle
{
    public virtual void MethodSlot3_FireAllNuclearMissiles() { }
}

class VehicleUser
{
    public delegate void OpenGasTankMethod(Car car);

    public void OpenGasTank(Vehicle vehicle, OpenGasTankMethod method)
    {
        //it's stopping you here from firing all nuclear weapons
        //by mistaking your car's gas tank for the armageddon switch
        method(vehicle); 
    }
}

當編譯器發出虛擬方法調用時,它只是將索引編譯到查找表中。 如果您可以僅僅因為它們都是車輛而進入需要核電的核潛艇,那么您可能認為您在調用Car方法(例如打開油箱),而實際上您只是在使Fallout系列游戲成為現實。

根據您的評論,這應該可以幫助您入門:

class Blah
{
    private List<Action<object>> _handlers = new List<Action<object>>();

    public void AddListener<T>(Action<T> handler)
    {
        //graceful type checking code goes in here somewhere
        _handlers.Add(o => handler((T) o));
    }

    void RaiseEvent(object eventArgs)
    {
        foreach (var handler in _handlers) handler(eventArgs);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM