为什么以下在委托中使用协方差的示例无法编译?

tig*_*rou 11 c# generics delegates covariance

我已经定义了以下委托类型.一个返回一个字符串,一个返回一个对象:

delegate object delobject();
delegate string delstring();
Run Code Online (Sandbox Code Playgroud)

现在考虑以下代码:

delstring a = () => "foo";
delobject b = a; //Does not compile!
Run Code Online (Sandbox Code Playgroud)

为什么作业无效?

我不明白.返回字符串的方法应该被安全地视为返回对象的方法(因为字符串是对象).


在C#4.0中,以下示例有效.我使用Func<TResult>泛型类型而不是使用委托:

Func<string> a = () => "foo";
Func<object> b = a; //Perfectly legal, thanks to covariance in generics
Run Code Online (Sandbox Code Playgroud)

另外:如果我以这种方式重写它,它的工作原理:

delobject b = () => a();
Run Code Online (Sandbox Code Playgroud)

但这与我最初想要的不一样.现在我创建了一个调用另一个方法的新方法.

它不仅仅是一个赋值,如下例所示:

delint a = () => 5;
delobject b = a; //Does not work, but this is OK, since "int" is a value type.
delobject b = () => a(); //This will box the integer to an object.
Run Code Online (Sandbox Code Playgroud)

小智 11

委托类型仍然是具体的对象类型.当你写作

delegate object delobject();
delegate string delstring();
Run Code Online (Sandbox Code Playgroud)

那么两个委托类型之间就没有"是一种"关系.您只需创建两种不同的类型.

就像

class A { public int i; };
class B { public int i; };
Run Code Online (Sandbox Code Playgroud)

A和之间没有隐式或显式转换B,即使没有任何可能A不会像a那样具有相同意义B,反之亦然.

共同和逆变Func意味着具体委托类型的作者已经决定Func<string>可以将其视为Func<object>,但是委托类型的作者可以决定,就像我的班级的作者B决定是否会也许更有意义的是从中衍生出来A.

可以做的是添加一个间接级别,而无需创建其他方法:

delstring a = () => "foo";
delobject b = new delobject(a); // or equivalently, a.Invoke
Run Code Online (Sandbox Code Playgroud)


aus*_*ush 5

Func标记的类型参数inout,因此您可以像这样将这些类型分配给另一个.这就是泛型的差异意味着什么.

delobjectdelstring它们是不同的类型,它们不是变体,因此您不能将它们分配给另一个.但是delobject你可以分配一个返回派生类型的处理程序,这就是委托中的方差.