c# - 为什么 ReadOnlyCollection 不允许协方差?

标签 c# covariance readonly-collection

此代码之所以有效,是因为 Enumerator无法修改集合:

var roList = new List<string>() { "One", "Two", "Three" };
IEnumerable<object> objEnum = roList;

如果我们尝试对 List<object> 做同样的事情, 而不是 IEnumerable<object> ,我们会得到一个编译器错误,告诉我们不能隐式转换类型 List<string>List<object> .好吧,这是有道理的,在我看来,这是微软的一个很好的决定,作为从数组中吸取的教训。

但是,我不明白的是,为什么这个强硬规则适用于 ReadOnlyCollection 之类的东西? ?我们将无法修改 ReadOnlyCollection 中的元素,那么导致 Microsoft 阻止我们对只读内容使用协变的安全问题是什么?是否有一种可能的方法来修改 Microsoft 试图解释的那种类型的集合,例如通过指针?

最佳答案

变体和逆变仅适用于接口(interface)和委托(delegate),不适用于类。

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

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

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


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

NO VARIANCE FOR TYPE PARAMETERS IN CLASSES

Only interfaces and delegates can have variant type parameters. Even if you have a class that only uses the type parameter for input (or only uses it for output), you can’t specify the in or out modifiers. For example Comparer<T>, the common implementation of IComparer<T>, is invariant — there’s no conversion from Comparer<IShape> to Comparer<Circle>.

Aside from any implementation difficulties that this might’ve incurred, I’d say it makes a certain amount of sense conceptually. Interfaces represent a way of looking at an object from a particular perspective, whereas classes are more rooted in the object’s actual type. This argument is weakened somewhat by inheritance letting you treat an object as an instance of any of the classes in it s inheritance hierarchy, admittedly. Either way, the CLR doesn’t allow it.

关于c# - 为什么 ReadOnlyCollection 不允许协方差?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25575873/

相关文章:

c# - 创建 winforms 帮助文件

c# - YouTube 数据 API (v3) 在 Windows 服务器 (IIS) 中托管

C# 泛型类型推断与协变 - 错误或限制

c# - 列表和只读属性

c# - 从 IList<> 返回 ReadOnlyCollection

c# - VS 2015 智能感知 : Exceptions Thrown not Previewed

c# - 为 protobuf-net 生成序列化程序集失败

c# - IList在c#中使用协变和逆变,这可能吗?

typescript - Typescript中协变和逆变位置的区别

c# - protobuf-net:无法反序列化 ReadOnlyCollection