2011-09-05 40 views
7

C#有一個conditional operator和IF語句,我懷疑條件運算符只是語法糖。所以在編譯時它會和IF操作一樣。爲什麼IF和條件運算符之間的IL有這樣的差別?

但是他們沒有(見下文),他們確實有不同的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爲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˚F或有條件

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) 
+3

可以肯定的是:你是否正在編譯版本模式(NOP使它看起來像調試模式乍一看)?在調試模式下,編譯器不會執行所有優化以使調試更容易。 –

+1

這是調試還是發佈模式?就我所知,穿插的'nop's被用於突破點。 –

+1

都處於發佈模式? –

回答

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!)

,這將是一個有趣的問題。他們爲什麼倒置?有沒有邏輯?

+0

葉,很好看。問題是發佈模式與調試模式。 –

+2

你說「唯一的區別」,但當然在'?'case','001b'-'0029'正在計算條件表達式的*值*,然後它最終被賦值給'002e'處的變量,而在if語句下,有兩種可能的賦值('000c'和'0014'),這當然可以是不相關的變量,而'if'語句不具有*值。 –

+0

@Damien_The_Unbeliever對。糾正。這告訴我,WinMerge是程序員最好的朋友:-) – xanatos

相關問題