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

本文关键字:函数 参数 CIL 反汇编 表达式 三元 | 更新日期: 2023-09-27 18:30:00

我很难在中对WriteLine()调用的参数进行CIL反汇编

FileInfo path = new FileInfo(@"c:'a.txt");
Console.WriteLine("prefix: " + path != null ? path.FullName : "null");

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)

在我看来,首先调用Concat,然后才调用三元操作员评估。特别是:

IL_0012似乎调用了Concat("prefix", path)
IL_0012brtrue.s IL_0020//基于先前返回值的分支

  • 为什么用path而不是path.FullName作为参数来调用Concat
  • 如果Concat的第一个参数是null,它是否返回null?如何编译器知道吗?(如果我用自己的plus(string, string)替换+拆卸成我更期待的东西。)

你能解释一下,反汇编是如何处理三元参数和对WriteLine的调用的吗?

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

这不是反汇编的问题,而是运算符优先级的问题。

您的表达式被评估为

("prefix: " + path != null) ? path : "null";

不作为

"prefix: " + (path != null ? path : "null");

正如你所期望的那样。只要正确使用括号,你就可以了:)

事实上,这是编译器遗漏的"优化"部分——由于string.Concat("prefix: ", whatever)可以从不为null,因此您将始终获得path.FullName。当然,一个只计算其中一个选项的三进制几乎肯定是一个错误,所以…