Marc是对的;只是为了给你更多的背景知道为什么这不起作用。考虑你的代码的下面重新命名:
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”协作的类型参数,以及您想要的类型参数与“in”是相反的。如果你这样做,那么编译器会检查你想要的变化是否是类型安全的。如果它不能,那么它将不允许该类型的声明。
这个问题通常在计算器上出现的方式是人们在问为什么是这个非法的:
List<Giraffe> giraffes = new List<Giraffe>();
List<Mammal> mammals = giraffes; // illegal
一样的道理。因为然后没有什么会阻止你从以后的
mammals.Add(new Tiger());
你刚刚添加一只老虎到长颈鹿名单。同样的推理,只是一个更简单的情况。
嘿,当我尝试做到这一点,它说它的C#4.0语言功能,我得到一个错误,我该怎么办? – Twinhelix 2011-05-09 10:00:44
@Twinhelix - 您使用的是哪个版本的Visual Studio,以及您定位的是哪个平台版本?它适用于VS2010,面向.NET 2.0。在C#4.0之前...差异不是非常有限的情况。 – 2011-05-09 10:02:56
它需要C#4.0。 – 2011-05-09 10:07:28