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)
Func标记的类型参数in和out,因此您可以像这样将这些类型分配给另一个.这就是泛型的差异意味着什么.
您delobject和delstring它们是不同的类型,它们不是变体,因此您不能将它们分配给另一个.但是delobject你可以分配一个返回派生类型的处理程序,这就是委托中的方差.