[英]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.