CIL反汇编涉及三元表达式的函数参数

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

Lua*_*aan 8

这不是拆卸的问题,而是操作员优先级的问题.

您的表达式被评估为

("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,所以...