背景
我知道编译器会“忽略为字段生成代码,例如int foo = 0;
,因为内存分配器会将字段初始化为默认值。”参考资料
class Foo
{
public int a = 1;
public int b = 0;
}
Foo..ctor:
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: stfld UserQuery+Foo.a // There is no b.
IL_0007: ldarg.0
IL_0008: call System.Object..ctor
IL_000D: ret
我知道"编译器会在使用局部变量的每个方法上自动添加
.locals init
,表示JIT必须在开始执行方法之前注入初始化所有局部变量的代码。"参考链接
问题
为什么编译器不会省略生成用于本地变量的IL代码,例如int foo = 0;
,因为.locals init
已经涵盖了这一点?(为了与字段保持一致性?)
(我理解C#规范要求局部变量被明确分配,我可以接受这一点。)
(我引用的链接说明了为什么需要.locals init
,以及为什么C#规范要求局部变量被初始化。但它没有说明为什么必须存在额外的IL指令来初始化默认值。由于验证过程已经由.locals init
保证)
void Main()
{
int a = 0;
int b = 1;
int c = 0;
int d = a + b + c;
d++;
}
.maxstack 2
.locals init (int a, int b, int c, int d)
IL_0000: ldc.i4.0
IL_0001: stloc.0 // a (Can be optimized away)
IL_0002: ldc.i4.1
IL_0003: stloc.1 // b
IL_0004: ldc.i4.0
IL_0005: stloc.2 // c (Can be optimized away)
IL_0006: ldloc.0 // a
IL_0007: ldloc.1 // b
IL_0008: add
IL_0009: ldloc.2 // c
IL_000A: add
IL_000B: stloc.3 // d
IL_000C: ldloc.3 // d
IL_000D: ldc.i4.1
IL_000E: add
IL_000F: stloc.3 // d
很重要,以及为什么C#规范要求必须初始化本地变量。但是它并没有说为什么必须存在额外的IL指令。(因为
.locals init`已经确保了验证过程) - colinfang