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是通用的,并且与所有数据类型一起使用,所以它可能在所有情况下都是额外的一步。思考?