c#。方差示例(Jon Skeet 书)

问题描述 投票:0回答:1

书中的第二个例子是从动态到对象的方向,对吗?也许应该从对象到动态?如果我的假设不正确,请更详细地解释原因。

为了将其转化为具体示例,让我们考虑一下

Func<in T, out TResult>
。规则含义如下:

  1. 存在从

    Func<object, int>
    Func<string, int>
    的有效转换,因为

    • 第一个类型参数是逆变的,并且存在隐式引用转换从字符串到对象
    • 第二个类型参数是协变的,并且存在从 int 到 int 的恒等转换。
  2. 存在从

    Func<dynamic, string>
    Func<object, IConvertible>
    的有效转换,因为

    • 第一个类型参数是逆变的,并且存在从动态到对象的恒等转换
    • 第二个类型参数是协变的,并且存在从字符串到 IConvertible 的隐式引用转换

代码片段取自 J. Skeet 所著的《C# in Depth》第四版,第 147 页。

c# covariance contravariance
1个回答
0
投票

逆变

为了简单起见,我们考虑委托仅采用参数:

Action<out TParam>
。我们可以将其视为一种方法:

void SomeMethod(TParam param);

或更具体地说:

void SomeMethod(string param);

因此,将此类方法分配给变量是完全有效的,例如并调用它:

Action<string> action = SomeMethod;
action("some value");

现在,让我们考虑一下

action
变量 - 它接受字符串参数,但是如果该变量引用
Action<object>
呢?如下:

// Note changed type of param
void SomeMethod(object param);

Action<string> action = SomeMethod;
// IMPORTANT - this is still perfectly valid
action("some value");

它仍然可以工作,因为

action
被声明为仅接受
string
的方法,所以只要
string
派生自,那么底层的内容(什么是 true 类型参数)并不真正让我们担心那种类型。

这就是逆变的全部内容,直线

Action<string> action = SomeMethod;
如果

SomeMethod

 的参数具有 
object
 类型,则 
仍然有效。

协方差

更简单。为了简单起见,让我们考虑一下

Func<in TResult>

TResult
是委托的返回类型。因此,如果方法返回
object
,它也可以返回较少的派生类型,并且结果仍然可以分配给基本类型,即:

Func<object> d1 = () => new object();
Func<string> d2 = () => "covariance";

现在,当你调用

d1()
时,你期望得到一个对象,当你调用
d2()
时,你期望得到一个字符串。由于
string
派生自
object
,如果该方法返回更多派生类型(例如字符串),
d1
的调用者不会“中断”。所以作业:

d1 = d2;

可以工作,因为返回类型仍然兼容。

这要归功于协方差(另一个例子可能是集合)。

将所有内容放在一起

我希望很清楚,现在

Func<TInput, TReult>
和其他代表(具有更多类型参数)只是我上面解释的一些组合:)

回到你的问题。

Func
委托中的第一个类型参数(当有两个以上类型参数时)是逆变的(带有
in
修饰符)。这意味着可以将较少派生类型分配给使用更多派生类型定义的变量。所以:

  1. Func<object, int>
    Func<string, int>
    - 正确,因为
    Func<**object**, int>
    可以分配给任何
    Func<whatever, int>
    ,因为
    whatever
    源自
    object

  2. Func<dynamic, string>
    Func<object, IConvertible>
    - 正确,因为
    Func<**dynamic**, int>
    可以分配给任何
    Func<object, int>
    ,因为
    object
    可以分配给
    dynamic

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.