此代码的工作原因是由于Enumerator
无法修改集合:
var roList = new List<string>() { "One", "Two", "Three" };
IEnumerable<object> objEnum = roList;
如果我们尝试使用List<object>
而不是IEnumerable<object>
执行相同的操作,我们会收到编译器错误,告诉我们我们无法隐式地将类型List<string>
转换为{{1} }}。好吧,那个是有道理的,在我看来,这是微软的一个很好的决定,作为从数组中吸取的教训。
但是,我无法弄清楚为什么世界上这条强硬性规则适用于List<object>
之类的东西?我们将无法修改ReadOnlyCollection
中的元素,因此导致Microsoft阻止我们使用只读内容的协方差的安全问题是什么?是否有可能修改Microsoft试图考虑的集合类型,例如通过指针?
答案 0 :(得分:8)
方差和逆变仅适用于接口和代理,而不适用于类。
但是,您可以这样做(使用.NET 4.5):
ReadOnlyCollection<string> roList = ...
IReadOnlyCollection<object> objects = roList;
(因为IReadOnlyCollection<T>
是协变的)
要回答关于为什么不允许在课堂上出现差异的问题,这里是Jon Skeet在他的C# in Depth一书(第二版,§13.3.5,第394页)中的解释。
课程类型参数无方差
只有接口和委托可以具有变体类型参数。甚至 如果你有一个只使用type参数输入的类(或者 仅用于输出),您无法指定
in
或out
改性剂。例如Comparer<T>
,常见的实现IComparer<T>
,是不变的 - 没有转换Comparer<IShape>
至Comparer<Circle>
。除了可能存在的任何实施困难之外 招致,我说它在概念上有一定的意义。 接口表示从特定对象查看对象的方式 透视,而类更多地植根于对象的实际 类型。这个论点因为让你继承而有所削弱 将对象视为其中任何类的实例 承认,继承等级。无论哪种方式,CLR都不允许 它