无法转换继承的通用?

时间:2011-11-02 13:11:33

标签: c# generics .net-2.0 covariance

我正在尝试以下方法,但它给了我一个编译器错误:

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。我必须自己施展吗?我读过有关协方差和逆变的内容,但我无法理解这一点。

2 个答案:

答案 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;
        }
    }
}