我正在尝试以下方法,但它给了我一个编译器错误:
public class MyManager<T> : where T:MyEventArgs
{
private Dictionary<EventHandler<T>, EventFilter<T>> m_cSubscriptions;
public void Subscribe<K>(EventHandler<K> _cHandler, EventFilter<K> _cFilter)
where K:T
{
try
{
// cannot convert EventHandler<K> to EventHandler<T>
m_cSubscriptions.Add(_cHandler, _cFilter);
}
catch (ArgumentException)
{
m_cSubscriptions[_cHandler] = _cFilter;
}
}
}
问题:为什么不能将处理程序从K转换为T?
我正在使用。net 2.0,因为我正在使用Unity3D。需要我自己铸造吗?我读过协方差和逆变,但我不明白这个
EventHandler<Derived>
不是EventHandler<Base>
。输入参数是逆变的。所以你的代码也不能在c# 4/。net 4中工作。
你可以通过创建一个包装器来解决这个问题(这个例子只适用于c# 3,但类似的代码可能适用于c# 2):
(s,e) => handler(s, (K)e)
但是使用这种强制转换会失去静态类型的安全性。
要在安全的方向上转换委托,可以使用我的ConvertDelegate<T>
方法。
我决定通过使用Delegate
并定义一个没有泛型的正常EventFilter
类来将字典更改为更常见的字典。我希望铸造是正确的,因为我还没有测试这个。我希望它能起作用。
public class MyManager<T> : where T:MyEventArgs
{
private Dictionary<Delegate, EventFilter> m_cSubscriptions;
public void Subscribe<K>(EventHandler<K> _cHandler, EventFilter<K> _cFilter)
where K:T
{
try
{
// cannot convert EventHandler<K> to EventHandler<T>
m_cSubscriptions.Add(_cHandler, _cFilter);
}
catch (ArgumentException)
{
m_cSubscriptions[_cHandler] = _cFilter;
}
}
}