我正在尝试以下方法,但它给了我一个编译器错误:
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。我必须自己施展吗?我读过有关协方差和逆变的内容,但我无法理解这一点。
答案 0 :(得分:0)
EventHandler<Derived>
不是EventHandler<Base>
。输入参数是反变量的。因此,您的代码也无法在C#4 / .net 4中运行。
您可以通过创建包装器来解决此问题(此示例仅适用于C#3,但C#2可以使用类似的代码):
(s,e) => handler(s, (K)e)
但是这种演员会失去静态类型的安全性。
要在安全方向转换代表,您可以使用我的ConvertDelegate<T>
方法。
答案 1 :(得分:0)
我决定使用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;
}
}
}