关于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>
接口不是协变的。