如果
IList<Elephant> elephants = new List<Elephant>();
IList<Animal> animalList = elephants;
是可能的,你可以再做到這一點
animalList.Add(new Animal());
但animalList
真的是相同的referrent作爲elephants
參考。並且因爲elephants
是IList<Elephant>
,您會嘗試將Animal
的實例添加到只能包含Elephant
實例的集合中。
IEnumerable<T>
可能的原因是IEnumerable<T>
是covariant在類型參數T
。這是因爲T
只出現在接口IEnumerable<T>
的「出」位置。由於您只是從IEnumerable<T>
消耗T
的實例,因此將IEnumerable<Derived>
的實例分配給類型爲IEnumerable<Base>
的變量是安全的。任何來自IEnumerable<Derived>
的是Base
,這就是爲什麼實施IEnumerable<Derived>
的東西可以安全地用作IEnumerable<Base>
。這就是爲什麼將IEnumerable<Elephant>
的實例分配給IEnumerable<Animal>
類型的變量是安全的。
但是,由於IList<T>
在類型參數T
中不是協變的,所以你遇到了問題IList<T>
。這裏的問題是T
出現在接口IList<T>
的「in」位置。因此,如果您可以將IList<Derived>
的實例分配給IList<Base>
類型的變量,那麼您可以嘗試將Base
的實例粘貼到IList<Base>
中,這實際上試圖將Base
的實例粘貼到IList<Derived>
的實例中,這顯然不安全。這正是我們剛剛遇到的IList<Elephant>
和IList<Animal>
的問題。
請注意,IList<T>
在類型參數T
中也不是相反的。這是因爲T
出現在接口IList<T>
的「出」位置。如果您可以將IList<Base>
的實例分配給IList<Derived>
類型的變量,那麼您可以嘗試從IList<Derived>
中獲取Derived
的實例,該實例將嘗試從IList<Base>
的實例中獲取實例Derived
,這顯然是荒謬的。
[關於C#協方差的問題](http:// stackoverflow。com/questions/4034495/question-about-c-sharp-covariance) – nawfal 2013-06-10 16:52:59