7

我有一本书解释了逆变/协方差,如下所示:

  • 委托可以具有比其方法目标更具体的参数类型。这称为逆变
  • 委托的返回类型可以比其目标方法的返回类型更具体。这称为协方差

而且,这是一个例子。

using System;

delegate void StringAction(string s);
delegate object ObjectRetriever();

class Test
{
    static void Main()
    {
        StringAction sa = new StringAction(ActionObject);
        sa("hello");

        ObjectRetriever o = new ObjectRetriever(RetrieveString);
        object result = o();
        Console.WriteLine(result);
    }


    static string RetrieveString() {return "hello";}

    static void ActionObject(object o)
    {
        Console.WriteLine(o);
    }
}

我认为为了使用协方差/逆变,需要使用new示例中所示的方法,但我似乎使用sa = ActionObjectand 得到了相同的结果o = RetrieveString。(我用 Mono 测试过)。

  • 那么,作者为什么用new协方差/逆变来解释呢?
  • 协方差/逆变思想背后的理论是什么?它只是一个花哨的名字描述object x = Everything inherit from object吗?这个奇怪的名字是从哪里来的?它的用途是什么?
4

4 回答 4

21

我有一本书解释了逆变/协方差如下......

这不是一个很好的方差解释。完全不清楚究竟什么是所谓的“协变”和“逆变”。

从未提及实际上是变体的东西。逆变的是从类型到具有该类型参数的委托的映射。逆变是映射关系的属性。

试着阅读这篇文章,看看你是否理解得更好:

http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx

我认为为了使用协方差/逆变,需要使用 new ,如示例中所示,但我似乎得到了相同的结果......

从 C# 2.0 开始,您可以说“d = M”或“d = new D(M)”——编译器只是将它们识别为编写同一事物的两种不同方式。

为什么作者使用 new 来解释协变/逆变?

我不知道。

协方差/逆变思想背后的理论是什么?

理论是,如果你有一个排序关系——也就是说,如果说 X x = (Y)y 是合法的,那么 X 比 Y 大——并且你有一个保留排序关系的映射,那么映射是协变的。如果它反转排序关系,它是逆变的。

例如,假设 Animal 是比 Giraffe 更大的类型。因此,您可以将 Giraffe 类型的对象分配给 Animal 类型的变量。动物 > 长颈鹿。

现在进行从类型 T 到方法 M-that-takes-aT 和委托类型 D-that-takes-aT 的映射。

您可以将方法 M-that-takes-an-Animal 分配给 D-that-takes-a-Giraffe 类型的变量。D(长颈鹿)> M(动物)但动物>长颈鹿。关系颠倒了映射逆变的。

它只是描述对象 x = 一切都继承自对象的花哨名称吗?

不,它那个概念有关,因为 object 是一种比几乎所有其他类型都大的类型但实际上变体是保留或反转大小关系的映射。

尝试阅读这篇文章,看看它是否有帮助。

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

这个奇怪的名字是从哪里来的?

范畴论。

于 2011-07-23T05:32:36.270 回答
2

我见过的描述 C# 中协变/逆变的最佳信息是 Eric Lippert 的一系列博客文章。请参阅从列表底部开始的十一部分系列。

有时读起来有点难。但它解释了你一开始可以问的一切。:)

它是在实际 C# 4.0 实现之前编写的,因此对语法的一些讨论已经过时,但其他一切似乎都按照描述的方式实现。

于 2011-07-23T02:03:16.403 回答
1

这是一篇很棒的 wiki 文章:这里

更重要的是漏斗倾倒的方向并将漏斗的宽度设置在适当的水平......

于 2011-07-23T02:13:10.217 回答
-1

不知道你在第一个问题中的意思。

第二个问题可以通过建议看演员来回答。逆变允许具有扩展类 B 的类 A 存储为类 B。

逆变

class A {
}

class B : public A {
}

B obj = new A();

协方差允许类 B 扩展类 A 但存储为类 A。

协方差

class A {
}

class B : public A {
}

A obj = new B();
于 2011-07-23T02:04:22.143 回答