从语言上讲,与方法相关的逆变是如何有意义的?

时间:2011-03-08 18:41:57

标签: .net delegates definition covariance contravariance

来自Wikipedia

协变:从更宽(双)转换为更窄(浮动) 逆变:从较窄(浮动)转换为较宽(双重)。

在.NET中,委托具有协方差,因为它允许委托的指定返回类型的派生类型是它拥有引用的方法的返回类型。

委托也有逆转,因为它允许委托的指定参数(参数)的派生类型是传递给它持有引用的方法的参数类型。

这两个定义与代表有关,它们不应该是协方差吗?在两个情况下,委托期望“更宽”的类型,但是给出“更窄的类型”。

有关MSDN的示例,请参阅here

那么逆变这个词在与代表有关的语言上是如何理解的呢?

2 个答案:

答案 0 :(得分:3)

http://blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx

最后一段有关于分配兼容性的简明摘要。

//从语言上讲,这似乎在参数与回归的意义上是合乎逻辑的 - 因此向前或向后的方向是关于进入或离开函数。

答案 1 :(得分:2)

我现在不同意SeanVDH的回答。他说:“从语言学的角度来看,这似乎在参数与回归的意义上是合乎逻辑的 - 所以前进或后退的方向是关于进入或离开该功能”。

相反,我认为这是来自here的答案:

协方差保留assignment compatibility并且逆变会使其反转。协方差是扩展转换,逆变是缩小转换。

  

当你实例化一个委托时,你   可以为其分配一个具有更多的方法   派生的返回类型   在委托中指定   (方差)。你也可以分配一个   参数类型 less 的方法   比代表中的那些派生的   (逆变)。 强调添加

示例:

static object GetObject() { return null; }
static void SetObject(object obj) { }

static string GetString() { return ""; }
static void SetString(string str) { }

static void Main()
{
    // Covariance. A delegate specifies a return type as object,
    // but I can assign a method that returns a string.
    Func<object> del = GetString;

    // Contravariance. A delegate specifies a parameter type as string,
    // but I can assign a method that takes an object.
    Action<string> del2 = SetObject;

    // But implicit conversion between generic delegates is not supported until C# 4.0.
    Func<string> del3 = GetString;
    Func<object> del4 = del3; // Compiler error here until C# 4.0.
}

这一认识是阅读Eric Lippert的文章,Jon Skeet的书 C#In Depth中快速跟踪的代表章节的协方差和逆变部分的结果,以及上面引用引号的链接。