如果我查看Linqpad中为以下两个代码片段创建的IL,我想知道这里发生了什么。
在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(最明确的是运行相应的编译器)。那里 没有 程序。
拿走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;
}
}
并从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
所以, 是,至少在这方面 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中指的是十六进制的常量值 2A
,这是小数点后42。所以,你去吧 不 最后执行更多指令。
我认为在C#情况下,编译器执行内存分配部分并在一个步骤中保存int的值,在VB情况下,DIM语句是第一步,它只分配内存,然后将值保存在第二步。 DIM是通用的,并且与所有数据类型一起使用,因此在所有情况下它可能都是额外的一步。思考?