Ковариантность, контравариантность и устранение лишних параметров типа

Учитывая следующую иерархию классов:

abstract class A {  }
abstract class B {  }
abstract class C {  }
abstract class D<TA, TB, TC>
  where TA : A
  where TB : B
  where TC : C {  }

class E : A {  }
class F : B {  }
class G : C {  }
class H : D<E, F, G> {  }

Я хочу создать простой универсальный метод для создания экземпляра объекта типа D:

void Create<TD>(string description)
  where TD : D
{
  var instance = Activator.CreateInstance<TD>();
}

Но компилятор принудительно указывает параметры типа для D, поэтому я должен написать следующее:

void Create<TD, TA, TB, TC>(string description)
  where TA : A
  where TB : B
  where TC : C
  where TD : D<TA, TB, TC>
{
  var instance = Activator.CreateInstance<D>();
}

Это означает, что вместо того, чтобы писать

Create<H>("foo");

я должен написать

Create<H, E, F, G>("foo");

Мой вопрос: поскольку я указываю H в качестве конкретного экземпляра, почему компилятору требуются дополнительные параметры типа для базового класса D в сигнатуре метода? Почему он не может просто вывести их из H?


person Ian Kemp    schedule 13.02.2012    source источник
comment
Ожидали ли вы, что where TL : List будет означать, что TL является некоторым закрытым List<>, но мне все равно, какое?   -  person AakashM    schedule 13.02.2012


Ответы (1)


where TD : D подразумевает, что D не является универсальным, а где где TD : D<TA, TB, TC> подразумевает, что D является универсальным.

person Candide    schedule 13.02.2012