繁体   English   中英

清单 <T> vs IEnumerable <T> :为什么此分配无效?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM