Why such a difference in IL between IF and the conditional operator?
C# has a conditional operator and IF statements and I suspected that the conditional operator would be just syntactic sugar. So at compile time it would have a the same as an IF operation.
However they do not (see below), they do have different IL. Trying to wrap my head around it and the assumption I have is that this is a performance optimisation that the conditional operator gets because it's limited scope.
Would like to know if my assumption is correct or not and maybe if there is more to this?
Also in the IF's IL there is some checks (L_000c, L_000d, L_000f) around int values which I can't figure out the meaning. This is what has lead me to think this is a more robust solution, at the cost of performance because of IF greater scope.
Code for IF
var result = "";
if (Environment.Is64BitOperatingSystem)
{
result = "Yes";
}
else
{
result = "No";
}
Console.WriteLine(result);
Code for conditional operator (I realise differences, but no matter how I change it - assign to variable etc... it makes very little difference)
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:开发者_StackOverflow社区 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)
if
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)
? (ternary operator)
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)
(nearly)same code for both in release mode. The if
adds a second stdloc.0
that isn't optimized away by the compiler. And the other difference is that the true
and false
are inverted.
(so I learn that I should ALWAYS fire up WinMerge!)
And THIS would be an interesting question. Why are they inverted? Is there any logic?
精彩评论