13

在 C# 中,所有委托类型都相互不兼容,即使它们具有相同的签名。举个例子:

delegate void D1();
delegate void D2();

D1 d1 = MethodGroup;
D2 d2 = d1;                           // compile time error
D2 d2 = new D2 (d1);                  // you need to do this instead

这种行为和语言设计决策背后的原因是什么。

4

3 回答 3

23

在 C# 中,所有委托类型都相互不兼容,即使它们具有相同的签名。这种行为和语言设计决策背后的原因是什么?

首先,我认为可以公平地说,许多运行时和语言设计者对这个决定感到遗憾。代表上的结构类型——即通过签名匹配——是一个经常被请求的特性,它看起来很奇怪,Func<int, bool>并且Predicate<int>不能自由地相互分配。

据我所知,这个决定背后的原因——我赶紧补充说,这个决定是在我开始加入 C# 团队之前大约六年做出的——是期望会有具有语义的委托类型。您希望这是一个类型错误:

AnyFunction<int, int> af = x=> { Console.WriteLine(x); return x + y; };
PureFunction<int, int> pf = af;

“纯”函数是一个不产生和不消耗副作用的函数,不消耗其参数之外的信息,并且在给定相同参数时返回一致的值。显然af至少失败了其中两个,因此不应分配给pf隐式转换。

但是充满语义的委托类型从未发生过,所以现在它有点错误。

于 2013-06-20T13:59:23.960 回答
15

基本上是因为编译器为您创建了两个类。你不能这样做的同样原因:

class A {}
class B {}

void Main()
{
    A a = new A();
    B b = a;
}

例如下面的代码

void Main() {}

delegate void D();
class C {}

IL代码是:

D.Invoke:

D.BeginInvoke:

D.EndInvoke:

D..ctor:

C..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  ret         
于 2013-06-20T13:10:07.480 回答
2

代表只不过是另一种类型。它们出于同样的原因不兼容,class A {}并且class B {}将不兼容。

delegate void D1();

将大致编译为:

class D1 : MulticastDelegate { .... } 
于 2013-06-20T13:11:51.350 回答