为什么ReadOnlyCollection不允许协方差?

时间:2014-08-29 20:36:51

标签: c# covariance readonly-collection

此代码的工作原因是由于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试图考虑的集合类型,例如通过指针?

1 个答案:

答案 0 :(得分:8)

方差和逆变仅适用于接口和代理,而不适用于类。

但是,您可以这样做(使用.NET 4.5):

ReadOnlyCollection<string> roList = ...
IReadOnlyCollection<object> objects = roList;

(因为IReadOnlyCollection<T>是协变的)


要回答关于为什么不允许在课堂上出现差异的问题,这里是Jon Skeet在他的C# in Depth一书(第二版,§13.3.5,第394页)中的解释。

  

课程类型参数无方差

     

只有接口和委托可以具有变体类型参数。甚至   如果你有一个只使用type参数输入的类(或者   仅用于输出),您无法指定inout   改性剂。例如Comparer<T>,常见的实现   IComparer<T>,是不变的 - 没有转换   Comparer<IShape>Comparer<Circle>

     

除了可能存在的任何实施困难之外   招致,我说它在概念上有一定的意义。   接口表示从特定对象查看对象的方式   透视,而类更多地植根于对象的实际   类型。这个论点因为让你继承而有所削弱   将对象视为其中任何类的实例   承认,继承等级。无论哪种方式,CLR都不允许   它