Mic*_*ann 0 c# cil disassembly
我在参与CIL反汇编参与WriteLine()调用时遇到了困难:
FileInfo path = new FileInfo(@"c:\a.txt");
Console.WriteLine("prefix: " + path != null ? path.FullName : "null");
Run Code Online (Sandbox Code Playgroud)
CIL解散
.locals init (
[0] class [mscorlib]System.IO.FileInfo path
)
// ...
IL_000c: ldstr "prefix: "
IL_0011: ldloc.0
IL_0012: call string [mscorlib]System.String::Concat(object, object)
IL_0017: brtrue.s IL_0020
IL_0019: ldstr "null"
IL_001e: br.s IL_0026
IL_0020: ldloc.0
IL_0021: callvirt instance string [mscorlib]System.IO.FileSystemInfo::get_FullName()
IL_0026: call void [mscorlib]System.Console::WriteLine(string)
Run Code Online (Sandbox Code Playgroud)
在我看来,它Concat首先被调用,然后才对三元运算符进行评估.特别是:
IL_0012 Concat("prefix", path)似乎被调用, //基于先前的返回值进行分支
IL_0012 brtrue.s IL_0020
Concat调用pathas而不是path.FullName?Concat返回null,如果它的第一个参数是null?编译器如何知道?(如果我+用我自己的替换plus(string, string),拆卸到我宁愿期待的东西.)你能解释一下,反汇编如何处理三元参数和调用WriteLine?
这不是拆卸的问题,而是操作员优先级的问题.
您的表达式被评估为
("prefix: " + path != null) ? path : "null";
Run Code Online (Sandbox Code Playgroud)
不是
"prefix: " + (path != null ? path : "null");
Run Code Online (Sandbox Code Playgroud)
正如你所期待的那样.只需正确使用括号,你就可以了:)
事实上,这是对编译器的部分错过了"优化" -因为string.Concat("prefix: ", whatever)可以永远为空,你会永远得到path.FullName.当然,一个只评估其中一个选项的三元组几乎肯定是一个bug,所以...