Не можете преобразовать унаследованный дженерик? - PullRequest
0 голосов
/ 02 ноября 2011

Я пытаюсь использовать следующий метод, но он выдает ошибку компилятора:

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 голосов
/ 03 ноября 2011

Я решил изменить словарь на более распространенный, используя 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;
        }
    }
}
0 голосов
/ 02 ноября 2011

An EventHandler<Derived> - это не EventHandler<Base>.Входные параметры противоположны.Таким образом, ваш код не будет работать и в C # 4 / .net 4.

Вы можете обойти это, создав обертку (Этот пример работает только с C # 3, но подобный код возможен с C #2):

(s,e) => handler(s, (K)e)

Но при этом приведении вы теряете безопасность статического типа.

Чтобы преобразовать делегатов в безопасном направлении, вы можете использовать мой метод ConvertDelegate<T>.

...