Вы правы в том, что упускаете что-то в отношении ко / контравариантности, поэтому определения должны быть рядом: ( источник )
Ковариация
Позволяет вам использовать более производный тип, чем изначально указан.
Вы можете назначить экземпляр IEnumerable переменной типа IEnumerable .
Contravariance
Позволяет вам использовать более общий (менее производный) тип, чем первоначально указанный.
Вы можете назначить экземпляр Action переменной типа Action .
Ваш обработчик животных определен с in
, и это делает его контравариантным. Таким образом, с вашим определением допустимо
IAnimalHandler<PersianCat> handler = new CatHandler();
с учетом
public class PersianCat : Cat { }
, и если вы подумаете об этом, имеет смысл, если вы обработчик кошки, чем вы можете обращаться с персидскими кошками. Не имеет значения, с какой кошкой вы обращаетесь, вы можете справиться со всеми.
Случай, который вы пытаетесь форсировать, не является законным:
IAnimalHandler<IAnimal> handler = new CatHandler();
с использованием моего персидского кота (и выделенного обработчика) это будет выглядеть так:
IAnimalHandler<Cat> handler = new PersianCatHandler();
Итак, у нас есть специальный обработчик, который может обрабатывать только персидских кошек, поэтому мы не можем дать ему просто случайного кота, он бы не знал, что с ним делать.
Так что в судебном деле и определении контравариантности выше more generic
Тип находится справа от присвоения CatHandler
(или IAnimalHandler<Cat>
) и присваивается менее общей (или более конкретной) переменной типа IAnimalHandler<PersianCat>
.