C# компилаторът по-умен ли е от компилатора VB.NET?

Ако погледна IL, който е създаден в Linqpad за следните два кодови фрагмента, се чудя какво се случва тук.

In c#

int i = 42;

води до следния IL код

IL_0000:  ret

докато във VB

Dim i As Integer = 42

it is

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

Очевидно компилаторът на c# разбира, че стойността никога не се използва и по този начин просто не връща нищо. Във VB.NET действителният код се превежда.

Това се дължи на разлики в оптимизацията на компилатора или има нещо друго в работата?

Актуализация: Само за да изясня това - просто въвеждам този един ред в LinqPad и разглеждам IL, който създава (най-определено чрез стартиране на съответния компилатор). Няма няма програма.


person Olaf    schedule 09.02.2012    source източник
comment
Вярвам, че C# компилаторът извършва повече оптимизации в момента (това почти сигурно ще се промени, когато Roslyn се появи). Но в този случай това е малко фалшива победа за C# компилатора, тъй като почти сигурно ще бъде оптимизиран от JIT компилатора така или иначе.   -  person Damien_The_Unbeliever    schedule 09.02.2012
comment
@AakashM: Докато пиша, това е всичко, което въвеждам в LinqPad. Няма друг код. LinqPad произвежда IL чрез компилиране във фонов режим.   -  person Olaf    schedule 09.02.2012
comment
Компилира ли се до същото в C# при отстраняване на грешки? Предполагам, че C# оптимизира повече, когато е в режим на освобождаване, отколкото VB.NET. Това е една от причините, поради които не можете да оценявате променливи в изданието в C#, които не се използват, докато можете във VB.NET. Предпочитам второто.   -  person Tim Schmelter    schedule 09.02.2012
comment
@Tim: Изобщо не компилирам - това е просто резултат от LinqPad IL.   -  person Olaf    schedule 09.02.2012
comment
LINQPad извиква CodeDomProviders за C# и VB, които се свързват с компилаторите CSC.exe и VB. Оттук и верността в преводите на IL. Можете да активирате/деактивирате оптимизациите на компилаторите в Редактиране | Предпочитания (или с бутон в лентата на състоянието в последните бета версии).   -  person Joe Albahari    schedule 09.02.2012
comment
@Joe: Наистина, когато заявките за Optimize са обърнати на false, IL кодът е същият. Кара ме да се чудя как тези заявки са оптимизирани (това ли е само ключът /optimize?). И все пак, както AakashM доказа, дори кодът за сглобяване се различава.   -  person Olaf    schedule 09.02.2012


Отговори (2)


Премахвайки въпроса за linqpad, стартирах vbc и csc с /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;
}

}

и получи тези CIL резултати от ILDASM:

За 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

Така че, да, поне в това отношение csc е „по-умен“ от vbc. Но се обзалагам, че 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 

в from-VB се отнася до постоянна стойност на hex 2A, която е 42 десетична. И така, накрая той на изпълнява повече инструкции.

person AakashM    schedule 09.02.2012
comment
добре, имаме и по-голям стек, както в 8 (C#) срещу 1 - person V4Vendetta; 09.02.2012

Мисля, че в случай на C# компилаторът прави частта за разпределение на паметта и запазва стойността на int в една стъпка, а в случай на VB DIM изразът е първата стъпка, която просто разпределя памет и след това стойността се запазва на втората стъпка. DIM е общ и се използва с всички типове данни, така че може да бъде нещо като една допълнителна стъпка във всички случаи. мисли?

person Mujtaba Hassan    schedule 09.02.2012