C# 为什么所有委托类型都彼此不兼容?

C# 为什么所有委托类型都彼此不兼容?,c#,C#,在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 这种行为和语言设计决策背后的原因是什么。基本上是因

在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

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

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

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         

委托只是另一种类型。它们不兼容的原因与
A类{}
B类{}
不兼容的原因相同

delegate void D1();
将大致编译为以下内容:

class D1 : MulticastDelegate { .... } 
在C#中,所有委托类型彼此不兼容,即使它们具有相同的签名。这种行为和语言设计决策背后的原因是什么

首先,我认为公平地说,许多运行时和语言设计师对这个决定感到遗憾。委托上的结构类型(即,通过签名进行匹配)是一个经常需要的功能,而
Func
谓词
不能自由分配给彼此似乎很奇怪

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

AnyFunction<int, int> af = x=> { Console.WriteLine(x); return x + y; };
PureFunction<int, int> pf = af;
AnyFunction af=x=>{Console.WriteLine(x);返回x+y;};
纯函数pf=af;
“纯”函数是一个函数,它不产生和使用任何副作用,不使用参数以外的信息,并且在给定相同参数时返回一致的值。显然,
af
至少有两个失败,因此不应作为隐式转换分配给
pf


但是充满语义的委托类型从未出现过,所以现在有点不合适。

我无法给出理由,但委托是一种原始的语言功能。从那时起,他们增加了lambda方法,而这些方法不会遇到同样的问题。@Brandon什么?lambda转换为委托(或表达式树),
Action
s和
Func
s只是委托类型,因此它们遵循完全相同的规则。委托调用也会在运行时检查。这是一种重要的优化,只支持严格的类型标识。这很快。@s区别在于Actions、Funcs和lambda表达式隐式转换为您指定给它们的委托类型,甚至允许稍有不同的签名,这正是OP所抱怨的。@Brandon关于
Action
s和
Func
s确实没有什么特别之处,他们的工作方式与任何其他代理类型完全相同。我必须记住“不完美”这个词。我会满怀爱意地记得,在很短的时间内,我得到了一个比埃里克·利珀特(Eric Lippert)票数更多的答案。