关于C#协方差的问题

时间:2010-10-27 14:44:36

标签: c# c#-4.0 covariance

在下面的代码中:

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;

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

4 个答案:

答案 0 :(得分: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> - 拳击转换没有'保留代表性。)

答案 1 :(得分:5)

比较声明(msdn)

public interface IEnumerable<out T> : IEnumerable

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

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

答案 2 :(得分:3)

没有

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

答案 3 :(得分:1)

IList<T>界面不协变。