关于C#协方差的问题

在下面的代码中:

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; 

不应该使用协方差来将派生types分配给基types?

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

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

 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的博客文章系列 ,或者观看关于NDC方差的video 。

基本上,方差只允许在保证安全的地方(并且以保留表示的方式,这就是为什么您不能将IEnumerable<int>转换为IEnumerable<object> – 装箱转换不保留表示)。

比较声明(msdn)

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

你看到这个神奇的话out吗? 这意味着协方差是开启的。

没有。

否则,你可以添加一个不同的I1实现给一个只包含C1的列表。

IList<T>接口不是协变的。