[英]IList<T> vs IEnumerable<T>: Why is this assignment invalid?
大象:动物...
IList<Elephant> elephants = new List<Elephant>();
IEnumerable<Animal> animalList = elephants;
这很好,但是..
IList<Elephant> elephants = new List<Elephant>();
IList<Animal> animalList = elephants;
引发错误。 这是为什么?
如果这
IList<Elephant> elephants = new List<Elephant>();
IList<Animal> animalList = elephants;
有可能你可以做到这一点
animalList.Add(new Animal());
但是animalList
实际上是对与elephants
相同的引用人的引用。 而且由于elephants
是一个IList<Elephant>
您将尝试将Animal
的实例添加到只能包含Elephant
实例的集合中。
IEnumerable<T>
可能的原因是IEnumerable<T>
在类型参数T
是协变的。 这是因为T
仅出现在IEnumerable<T>
接口的“ out”位置。 由于您仅使用IEnumerable<T>
的T
实例,因此将IEnumerable<Derived>
实例分配给IEnumerable<Base>
类型的变量是安全的。 IEnumerable<Derived>
任何内容都是Base
,这就是为什么实现IEnumerable<Derived>
可以安全地用作IEnumerable<Base>
。 这就是将IEnumerable<Elephant>
实例分配给IEnumerable<Animal>
类型的变量的原因。
但是您会遇到IList<T>
麻烦,因为IList<T>
在类型参数T
不是协变的。 这里的问题是T
出现在接口IList<T>
“ in”位置。 因此,如果您可以将IList<Derived>
实例分配给IList<Base>
类型的变量,那么您可以尝试将Base
实例粘贴到IList<Base>
,这实际上将试图将Base
的实例粘贴到IList<Derived>
的实例中IList<Derived>
,这显然是不安全的。 这正是我们刚遇到IList<Elephant>
和IList<Animal>
。
注意, IList<T>
在类型参数T
也不是互变的。 这是因为T
在接口IList<T>
“ out”位置出现。 如果你能分配的实例IList<Base>
到类型变量IList<Derived>
,那么你可以尝试抢的实例Derived
出的IList<Derived>
这将是试图抓住一个实例Derived
出的一个实例IList<Base>
,这显然是荒谬的。
这称为协方差和逆 方差 。
我不会详细介绍,但您可以阅读 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.