C # ковариация на абстрактно реализованном интерфейсе - PullRequest
3 голосов
/ 15 июля 2011

Использование C # /. NET 4.0 Я надеялся, что будет возможен следующий сценарий:

interface IA<out TB> where TB : IB { }
interface IB { }

class A<TB> : IA<TB> where TB : IB { }
class B : IB { }


abstract class AbstractA<TB> : IA<TB> where TB : IB { }
class DerivedA<TB> : AbstractA<TB> where TB : IB { }

static void Main(string[] args) {
    var myAB = new A<B>();
    Debug.Assert(myAB is IA<B>); // fine
    Debug.Assert(myAB is IA<IB>); // fine

    var myDerivedAB = new DerivedA<B>();
    Debug.Assert(myDerivedAB is IA<IB>); // fine
    Debug.Assert(myDerivedAB is DerivedA<B>); // fine
    Debug.Assert(myDerivedAB is DerivedA<IB>); // NOT fine        
}

К сожалению, последний тест не удался, хотя типы явно совместимы.Был бы другой способ проверить это, кроме тестирования для каждой известной реализации IB?

class FirstB : IB { }
class SecondB : IB { }
Debug.Assert(myDerivedAB is DerivedA<FirstB> || myDerivedAB is DerivedA<SecondB>) 

Ответы [ 2 ]

5 голосов
/ 15 июля 2011

хотя типы явно совместимы

Нет, это не так;Ковариантность C # через out применяется только к интерфейсам и делегатам (ссылочных типов, хотя это нормально здесь).Это не относится к таким классам, как Derived<T>.

1 голос
/ 15 июля 2011

Вы можете использовать метод GetGenericArguments объекта Type:

Type t = myDerivedAB.GetType();
if (t.IsGenericType)
{
    Type[] typeArguments = t.GetGenericArguments();
    Debug.Assert(typeArguments.Length > 0 && typeArguments[0] is IB);
}

Таким образом вы можете получить параметр Generic объекта myDerivedAB и проверить его тип или что-то еще, что вам нужно.

...