如何列出<;派生类>;被分配给IEnumerable<;基类>;参数
本文关键字:gt lt IEnumerable 基类 分配 参数 何列出 派生 | 更新日期: 2023-09-27 18:20:13
我知道List<>的不能直接分配给List<>基类的。但是它如何允许分配相同的列表<>的值转换为IEnumerable<>基类参数的类型。
public class Base
{}
public class Derived : Base
{}
public class Test
{
// inside some method...
List<Derived> someElements;
ReadElements(someElements);
public void ReadElements(List<Base> elements) // this throws compile error
{...}
public void ReadElements(IEnumerable<Base> elements) // this one works
{...}
}
我知道List
是IEnumerable
的实现,支持索引和修改元素,但我似乎不理解这一部分?有人能解释一下吗?谢谢
因为IEnumerable<T>
的声明实际上是:
public interface IEnumerable<out T> : IEnumerable
并且CCD_ 4比特表示CCD_。
而List<T>
的声明没有方差注释,因此T
是不变的。
IList
和List
没有将它们的T
定义为out
,而IEnumerable
定义为。List
是一个类,因此不能有out
,而IList
不定义out
,因为它接受类型为T
的输入。
简单地说,你只能从IEnumerable
返回T
,但你可以将T
放入IList
,因为IEnumerable
不在乎你是否不那么具体,但IList
在乎。(事实上,这是必须的,请参阅@ChrisShain的回答,了解协方差和反方差是如何工作的)。
考虑一下这个代码,它本身是完全合法的:
public void AddElements(List<Base> elements)
{
Base item = new Base();
elements.Add(item);
}
但如果你这样称呼它会发生什么:
List<Derived> elements = new List<Derived>;
AddElements(elements);
类Base
不是从Derived
继承的,因此不能添加到elements
列表中。这是一个潜在的问题,因此是非法的。
另一方面,IEnumerable<Base>
只提供读取集合的方法,而不提供对集合的写入,因此不可能出现上述矛盾。
因为IEnumerable对于类型参数T是协变的:http://geekswithblogs.net/abhijeetp/archive/2010/01/10/covariance-and-contravariance-in-c-4.0.aspx