Марк прав;просто чтобы дать вам дополнительную информацию о том, почему это не может работать.Рассмотрим следующее переименование вашего кода:
interface IZoo<TCage, TAnimal>
where TCage : ICage<TAnimal>
where TAnimal : IAnimal
{
}
class Zoo<TCage, TAnimal> : IZoo<TCage, TAnimal>
where TCage : ICage<TAnimal>
where TAnimal : IAnimal
{
}
interface ICage<TAnimal> where TAnimal : IAnimal
{
}
interface IAnimal
{
}
class FishTank<TAnimal> : ICage<TAnimal> where TAnimal : IAnimal
{
}
class Fish : IAnimal
{
}
А теперь ваш вопрос, почему это не разрешено:
Zoo<FishTank<Fish>, Fish> aquarium = new Zoo<FishTank<Fish>, Fish>();
IZoo<ICage<IAnimal>, IAnimal> zoo = aquarium;
?
Поскольку предположим, что сейчасна IZoo есть метод:
interface IZoo<TCage, TAnimal>
where TCage : ICage<TAnimal>
where TAnimal : IAnimal
{
void PutAnimalInCage(TCage cage, TAnimal animal);
}
И тогда вы говорите:
zoo.PutAnimalInCage(giraffePaddock, giraffe);
И вы просто кладете загон для жирафов в аквариум!Мы не можем поддерживать безопасность типов в мире, где желаемое преобразование является законным, и у IZoo может быть любой выбранный вами метод.
Теперь это опасно, потому что у IZoo есть такой метод.Если у него нет такого метода, тогда вы правы, это может быть совершенно безопасно.В C # 4.0 мы добавили функцию к языку, чтобы вы могли попросить компилятор «проверить, можно ли сделать этот интерфейс безопасным вариантом», пометив параметры типа, которые вы хотите быть ковариантными с «out», и те, которые вы хотитебыть противоречивым с "в".Если вы сделаете это, то компилятор проверит для вас, может ли отклонение, которое вы хотите, сделать безопасным для типов.Если это невозможно, тогда он не разрешит объявление типа.
То, как этот вопрос обычно возникает в StackOverflow, - это люди, спрашивающие, почему это незаконно:
List<Giraffe> giraffes = new List<Giraffe>();
List<Mammal> mammals = giraffes; // illegal
По той же причине.Потому что тогда ничто не помешает вам позже
mammals.Add(new Tiger());
, и вы только что добавили тигра в список жирафов.Те же рассуждения, только намного более простой случай.