隐式方法组转换成功
本文关键字:转换 成功 方法 | 更新日期: 2023-09-27 18:20:48
我想知道为什么给定代码的输出(在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()方法对两个不同的对象执行引用比较有关(编译器显示相应的警告):
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 <<reference comparison
您可以使用以下代码来避免该问题:
bool Compare1(Delegate x) {
return x == (Delegate)((Action)Main);
}