在下面的代码中:
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;
协方差不应该允许我将派生类型分配给基类型吗?
答案 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>
界面不协变。