【发布时间】:2018-06-01 14:21:37
【问题描述】:
在逆变中,引用的赋值兼容性被颠倒是什么意思?
协变和逆变(C#)
// Assignment compatibility. string str = "test"; // An object of a more derived type is assigned to an object of a less derived type. object obj = str; // Covariance. IEnumerable<string> strings = new List<string>(); // An object that is instantiated with a more derived type argument // is assigned to an object instantiated with a less derived type argument. // Assignment compatibility is preserved. IEnumerable<object> objects = strings; // Contravariance. // Assume that the following method is in the class: // static void SetObject(object o) { } Action<object> actObject = SetObject; // An object that is instantiated with a less derived type argument // is assigned to an object instantiated with a more derived type argument. // Assignment compatibility is reversed. Action<string> actString = actObject;
参考: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/covariance-contravariance/
此外,当尝试从派生较少的类型转换为派生较多的类型时,会抛出InvalidCastException。由于不允许用户定义的转换到基类或从基类,我看不出方法组的逆变是如何工作的——不会/不应该调用这样的方法抛出一个@ 987654328@也是?
【问题讨论】:
-
我不明白你的问题。您要求/表现得好像 允许逆变 是必须在 C# 语言的规则内 实现的东西,当然不是这样。语言的规则已更改以允许逆变发生。
-
@Damien_The_Unbeliever 我已经阅读了几篇关于它的介绍如何潜在地破坏代码的文章(csharp.2000things.com/tag/assignment-compatibilityblogs.msdn.microsoft.com/ericlippert/2009/03/19/…csharpindepth.com/Articles/General/Overloading.aspx)
-
逆变是观察到,如果一个参数应该是一个
object,那么它当然也可以是一个string(这是一个object),并且代表应该适应因此,每个Action<object>都可以被视为Action<string>,因为Action不会询问string,而不是询问任何旧的object。所涉及的转换是从string到object的微不足道的转换,而不是相反,并且不涉及用户定义的转换。 -
(object < string) => (Action<string> < Action<object>)(in T),因为Action<object>是赋值兼容的(表示保留),在参数T中,与(可以存储到)Action<string>。因此,Action<T>在 T 上是逆变的。
标签: c# .net contravariance