Ух ты, этот вопрос часто поднимался в последнее время.
Краткий ответ: Нет, это невозможно.Вот что возможно возможно:
public void CallAllMethodsInContainer<T>(MyContainer<T> container) where T : IMyInterface
{
foreach (IMyInterface myClass in container.Contents)
{
myClass.MyMethod();
}
}
И вот почему то, что вы пытались , не возможно (взято из моего недавнего ответа ):
Рассмотрим тип List<T>
.Скажем, у вас есть List<string>
и List<object>
.строка происходит от объекта, но из этого не следует, что List<string>
происходит от List<object>
;в противном случае вы могли бы иметь такой код:
var strings = new List<string>();
// If this cast were possible...
var objects = (List<object>)strings;
// ...crap! then you could add a DateTime to a List<string>!
objects.Add(new DateTime(2010, 8, 23));23));
Приведенный выше код иллюстрирует, что значит быть (а не быть) ковариантным типом .Обратите внимание, что приведение типа T<D>
к другому типу T<B>
, где D
происходит от B
, возможно (в .NET 4.0), если T
равно ковариант ;универсальный тип является ковариантным, если его аргумент универсального типа только когда-либо появляется в виде выходных данных, т. е. свойства только для чтения и возвращаемые значения функций. поставляет B
, тогда тот, который всегда поставляет D
(T<D>
), сможет работать как T<B>
, поскольку все D
с B
с.
Между прочим, тип является контравариантным , если его универсальный параметр типа только когда-либо появляется в форме ввода - то есть, параметров метода.Если тип T<B>
является контравариантным, его можно привести к T<D>
, как бы странно это ни казалось.
Подумайте об этом так: если для какого-то типа T<B>
всегда требуетсяB
, затем он может перейти к тому, который всегда требует D
, поскольку, опять же, все D
с B
с.
Ваш класс MyContainer
не является ковариантными не контравариантно, потому что его параметр типа появляется в обоих контекстах - как ввод (через Contents.Add
) и как вывод (через само свойство Contents
).