Я бы не назвал это "ковариацией". Это - общая c дисперсия. Ваш код демонстрирует только общие ограничения c.
Давайте посмотрим, что мы можем сделать в каждом из методов Wash
. В первом методе Wash
мы можем:
public static void Wash(Stack<Animal> animals) {
animals.Push(new Animal());
Animal a = animals.Pop();
}
Теперь предположим, что у вас есть Stack<Bear> bears;
, и вы хотите передать его в первый Wash
. Вы видите, как это создаст противоречие, если компилятор позволил вам это сделать? Вы не можете добавить Animal
к Stack<Bear>
! Но что касается Wash
, то добавление Animal
вполне нормально, потому что известно только то, что он может принять Stack<Animal>
!
Следовательно, Stack<Bear>
не является подтипом Stack<Animal>
, поскольку вы не можете добавить Animal
s к первому, но вы можете добавить ко второму.
Во втором методе Wash
, хотя вы можете передать ему bears
, вы не можете добавить Animal
s до ti:
public static void Wash<T>(Stack<T> animals) where T: Animal {
animals.Push(new Animal()); // error
Animal a = animals.Pop();
}
Поскольку компилятор не уверен, что Stack<T>
является Stack<Animal>
. Это может быть , но также может быть Stack<Bear>
или Stack<Unicorn>
или Stack<SomeOtherSubclassOfAnimal>
, верно?