11

如果我看看Linqpad中爲以下兩個代碼片段創建的IL,我不知道這裏會發生什麼。c#編譯器比VB.NET編譯器更聰明嗎?

在C#

int i = 42; 

導致以下IL代碼

IL_0000: ret 

而在VB

Dim i As Integer = 42 

它是

IL_0000: ldc.i4.s 2A 
IL_0002: stloc.0 

顯然,c#編譯器明白這個值從來不會被使用,因此只是簡單的返回任何東西。在VB.NET中,實際的代碼被翻譯。

這是由於編譯器優化的差異還是有其他的工作?爲了澄清這一點 - 我只需將這一行輸入到LinqPad中,並查看它創建的IL(絕對是通過運行各自的編譯器)。 程序。

+0

我認爲C#編譯器進行更多的優化,目前(當羅斯林進來這幾乎肯定會發生變化)。但在這種情況下,這對C#編譯器來說有點虛假,因爲無論如何它幾乎肯定會被JIT編譯器優化。 – 2012-02-09 10:59:28

+0

@AakashM:正如我寫的,這是我進入LinqPad.There沒有其他的代碼。 LinqPad通過在後臺編譯產生IL。 – Olaf 2012-02-09 11:00:46

+0

它在調試中是否編譯到C#中?我假設C#在發佈模式和VB.NET時進行了更多的優化。這就是爲什麼你不能在C#中使用VB.NET中的變量來評估變量的原因之一。我更喜歡後者。 – 2012-02-09 11:01:09

回答

10

帶走linqpad問題,我跑vbccsc/optimize+ /debug-對這些程序:

Module f 

Public Sub Main() 
    Dim i As Integer = 42 
End Sub 

End Module 

public static class f 
{ 

public static void Main() 
{ 
    int i = 42; 
} 

} 

,並得到了ILDASM這些CIL結果:

對於VB:

.method public static void Main() cil managed 
{ 
    .entrypoint 
    .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = (01 00 00 00) 
    // Code size  4 (0x4) 
    .maxstack 1 
    .locals init (int32 V_0) 
    IL_0000: ldc.i4.s 42 
    IL_0002: stloc.0 
    IL_0003: ret 
} // end of method f::Main 

對於C#:

.method public hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  1 (0x1) 
    .maxstack 8 
    IL_0000: ret 
} // end of method f::Main 

所以,,至少在這方面cscvbc '聰明'。但我敢打賭,JITter會在執行時刪除任何差異。

編輯

我檢查,並實際執行的本地代碼不同的,至少在我的系統。我把兩個Console.ReadLine()電話給我一個機會,附加調試器,和我這些反彙編:

從VB:

00000000 sub   rsp,38h 
00000004 mov   dword ptr [rsp+20h],0 
0000000c mov   rax,7FF000434D8h 
00000016 mov   eax,dword ptr [rax] 
00000018 test  eax,eax 
0000001a je   0000000000000021 
0000001c call  FFFFFFFFE45BA230 
00000021 mov   dword ptr [rsp+20h],2Ah 
00000029 call  FFFFFFFFE26ABF20 
0000002e mov   qword ptr [rsp+28h],rax 
00000033 nop 
00000034 jmp   0000000000000036 
00000036 add   rsp,38h 
0000003a ret 

從C#:

00000000 sub   rsp,38h 
00000004 mov   rax,7FF000534D8h 
0000000e mov   eax,dword ptr [rax] 
00000010 test  eax,eax 
00000012 je   0000000000000019 
00000014 call  FFFFFFFFE45AA230 
00000019 call  FFFFFFFFE391BF20 
0000001e mov   qword ptr [rsp+20h],rax 
00000023 nop 
00000024 jmp   0000000000000026 
00000026 add   rsp,38h 
0000002a ret 

現在,我的裝配幾乎不存在,但即使我可以看到,

mov   dword ptr [rsp+20h],2Ah 

in來自-VB的是指十進制42的十六進制值2A的恆定值。所以你去,它確實到底執行更多的指令。

+2

好吧,我們也有一個更大的堆棧,如8(C#)與1 – V4Vendetta 2012-02-09 11:16:49

1

我想在C#情況下,編譯器內存分配部分和一個步驟和VB的情況下DIM語句節約整型值是第一步,剛剛分配內存,則該值爲節省第二步。 DIM是通用的,並且與所有數據類型一起使用,所以它可能在所有情況下都是額外的一步。思考?