关于C#协方差的问题

问题描述 投票:15回答:4

在下面的代码中:

interface I1 { }
class CI1: I1 { }

List<CI1> listOfCI1 = new List<CI1>();

IEnumerable<I1> enumerableOfI1 = listOfCI1; //this works

IList<I1> listofI1 = listOfCI1; //this does not

我可以将我的“listOfCI1”分配给IEnumerable<I1>(由于协方差)

但为什么我不能将它分配给IList<I1>?就此而言,我甚至无法做到以下几点:

List<I1> listOfI12 = listOfCI1;

协方差不应该允许我将派生类型分配给基类型吗?

c# c#-4.0 covariance
4个回答
24
投票

简而言之,IList<T>不是协变的,而IEnumerable<T>则是。这就是为什么......

假设IList<T>是协变的。下面的代码显然不是类型安全的......但是你想要错误在哪里?

IList<Apple> apples = new List<Apple>();
IList<Fruit> fruitBasket = apples;
fruitBasket.Add(new Banana()); // Aargh! Added a Banana to a bunch of Apples!
Apple apple = apples[0]; // This should be okay, but wouldn't be

关于方差的大量细节,请参阅Eric Lippert的blog post series,或观看我谈论NDC变异的video

基本上,方差只允许保证是安全的(并且以表示保持的方式,这就是为什么你不能将IEnumerable<int>转换为IEnumerable<object> - 拳击转换不保留表示)。


5
投票

比较声明(msdn)

public interface IEnumerable<out T> : IEnumerable

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable

你看到那个神奇的词out?这意味着协方差已经开启。


3
投票

没有。

否则,您可以将I1的不同实现添加到仅包含C1s的列表中。


1
投票

IList<T>界面不协变。

© www.soinside.com 2019 - 2024. All rights reserved.