隐式方法组转换问题

我想知道为什么给定代码的输出(在LinqPad中执行)

void Main() { Compare1((Action)Main).Dump(); Compare2(Main).Dump(); } bool Compare1(Delegate x) { return x == (Action)Main; } bool Compare2(Action x) { return x == Main; } 

总是:

  False True 

在这两种情况下,我都天真地期望它是True

这是在编译为IL然后反编译回C#时的外观。 请注意,在这两种情况下都有new Action(Main) – 一个新的引用对象(委托),其中包含指向存储在其中的实际方法的指针。

 private static void Main() { Program.Compare1(new Action(Program.Main)).Dump(); Program.Compare2(new Action(Program.Main)).Dump(); Console.ReadLine(); } private static bool Compare1(Delegate x) { return x == new Action(Program.Main); } private static bool Compare2(Action x) { return x == new Action(Program.Main); } 

如果那时我们看看CIL,前者使用ceq (引用比较),后者使用call bool [mscorlib]System.Delegate::op_Equality(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)来比较代表。

首先返回false因为包装代理的操作是两个不同的引用对象。

第二个返回true因为在Delegate类上实现的相等运算符比较包装器(操作)中的实际目标。

false结果与Compare1()方法在两个不同的对象上执行引用比较这一事实有关(compilator显示相应的警告):

 IL_0001: ldarg.0 IL_0002: ldnull IL_0003: ldftn instance void ConsoleApplication1.Test::Main() IL_0009: newobj instance void [System.Core]System.Action::.ctor(object, native int) IL_000e: ceq < 

您可以使用以下代码避免此问题:

 bool Compare1(Delegate x) { return x == (Delegate)((Action)Main); }