我知道编译器会"省略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
Run Code Online (Sandbox Code Playgroud)
我也知道"编译器会自动添加.locals init每个使用局部变量的方法,表明JIT必须在开始执行方法之前注入初始化所有局部变量的代码." 参考
为什么编译器没有int foo = 0;为局部变量之类的东西省略生成IL,因为.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
Run Code Online (Sandbox Code Playgroud)
为什么编译器不省略为
int foo = 0;局部变量等内容生成 IL,因为.locals init已经涵盖了这一点?
为什么应该这样?我实际上还没有验证这一点,但如果您删除了不必要的初始化,JIT 编译器会生成不同的本机代码,我会感到惊讶。
这意味着向 C# 编译器添加此优化的唯一好处是使 JIT 编译速度稍快一些(因为它必须处理更少量的 IL 代码)。看来 C# 编译器的作者为了这么小的好处而进行这种优化是不值得的。
| 归档时间: |
|
| 查看次数: |
464 次 |
| 最近记录: |