为什么IF和条件运算符之间的IL有这么大差异?

时间:2011-09-05 13:41:29

标签: c# il

C#有conditional operator和IF语句,我怀疑条件运算符只是语法糖。因此在编译时它将与IF操作相同。

然而,他们没有(见下文),他们确实有不同的IL。试图绕过它,我的假设是这是条件运算符得到的性能优化,因为它的范围有限。

想知道我的假设是否正确,也许还有更多内容?

同样在IF的IL中,有一些关于int值的检查(L_000c,L_000d,L_000f),我无法弄清楚其含义。这使我认为这是一个更强大的解决方案,因为IF的范围更大,性能成本。

<小时/> IF的代码

var result = "";
if (Environment.Is64BitOperatingSystem)
{
    result = "Yes";
}
else
{
    result = "No";
}
Console.WriteLine(result);

条件运算符的代码(我意识到差异,但无论我如何改变它 - 分配给变量等......它的差别很小)

Console.WriteLine("Is the OS x64? {0}", Environment.Is64BitOperatingSystem ? "Yes" : "No");

IL for IF

L_0001: ldstr ""
L_0006: stloc.0 
L_0007: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
L_000c: ldc.i4.0 
L_000d: ceq 
L_000f: stloc.2 
L_0010: ldloc.2 
L_0011: brtrue.s L_001d
L_0013: nop 
L_0014: ldstr "Yes"
L_0019: stloc.0 
L_001a: nop 
L_001b: br.s L_0025
L_001d: nop 
L_001e: ldstr "No"
L_0023: stloc.0 
L_0024: nop 
L_0025: ldloc.0 
L_0026: call void [mscorlib]System.Console::WriteLine(string)

IL for Conditional

L_002c: ldstr "Is the OS x64? {0}"
L_0031: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
L_0036: brtrue.s L_003f
L_0038: ldstr "No"
L_003d: br.s L_0044
L_003f: ldstr "Yes"
L_0044: call void [mscorlib]System.Console::WriteLine(string, object)

1 个答案:

答案 0 :(得分:6)

如果

IL_0000:  call       bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
IL_0005:  brfalse.s  IL_000f
IL_0007:  ldstr      "Yes"
IL_000c:  stloc.0                  // <------ Difference 1
IL_000d:  br.s       IL_0015
IL_000f:  ldstr      "No"
IL_0014:  stloc.0
IL_0015:  ldloc.0
IL_0016:  call       void [mscorlib]System.Console::WriteLine(string)

<强>? (三元运营商

IL_001b:  call       bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
IL_0020:  brtrue.s   IL_0029
IL_0022:  ldstr      "No"          // <------ Difference 2
IL_0027:  br.s       IL_002e
IL_0029:  ldstr      "Yes"
IL_002e:  stloc.0
IL_002f:  ldloc.0
IL_0030:  call       void [mscorlib]System.Console::WriteLine(string)

(几乎)在发布模式下的相同代码。 if添加了第二个stdloc.0,但未被编译器优化。另一个区别是truefalse被颠倒了。

(所以我知道我应该总是激活WinMerge!)

这将是一个有趣的问题。他们为什么倒?有什么逻辑吗?