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