C# 为什么';编译器优化掉重复的局部变量默认值初始化? 背景

C# 为什么';编译器优化掉重复的局部变量默认值初始化? 背景,c#,clr,il,C#,Clr,Il,我知道编译器会“忽略为字段生成代码,比如intfoo=0;,因为内存分配器会将字段初始化为默认值。” 我还知道“编译器会在每个使用局部变量的方法上自动添加.locals init,这表明JIT必须在开始执行方法之前注入初始化所有局部变量的代码。” 问题: 为什么编译器不忽略为intfoo=0?(是否与字段一致?) (我理解C#规范要求明确指定局部变量,我同意。) (我引用的链接说明了为什么需要.locals init,以及为什么C#spec要求初始化局部变量。但它没有说明为什么必须存在初始化默认

我知道编译器会“忽略为字段生成代码,比如
intfoo=0;
,因为内存分配器会将字段初始化为默认值。”

我还知道“编译器会在每个使用局部变量的方法上自动添加
.locals init
,这表明JIT必须在开始执行方法之前注入初始化所有局部变量的代码。”

问题: 为什么编译器不忽略为
intfoo=0.locals init
已经涵盖了局部变量的代码>?(是否与字段一致?)

(我理解C#规范要求明确指定局部变量,我同意。)

(我引用的链接说明了为什么需要
.locals init
,以及为什么C#spec要求初始化局部变量。但它没有说明为什么必须存在初始化默认值的附加IL指令。因为验证过程已经由
.locals init
确定了)

为什么编译器不忽略为
intfoo=0.locals init
已经涵盖了局部变量的代码>

为什么要这样做?我还没有实际验证过这一点,但是如果删除了不必要的初始化,JIT编译器会生成不同的本机代码,我会感到惊讶


这意味着,将这种优化添加到C#编译器中的唯一好处是使JIT编译稍微快一点(因为它必须处理更少的IL代码)。C#编译器的作者们似乎认为,为了这么小的好处而进行这种优化是不值得的。

是否
.locals init
涵盖了这种情况?这些是成员变量而不是局部变量,因此处理方式不同?好吧,我明白你的意思了,你澄清了这个例子。似乎回答了这个问题。如果我猜,我会说这与变量的碳足迹有关,当方法执行完后,它将被gc处理,该类必须使用idisposable@JimMischel我不认为答案。它说明了为什么
.locals init
非常重要,以及为什么C#spec要求初始化局部变量。但它没有说明为什么必须存在额外的IL指令。(由于验证过程由
.locals init
保证)我知道局部变量情况下没有性能差异。但在现场案例中也没有区别。而且他们确实在字段上进行了优化,为什么不在变量上进行同样的优化呢?@colinfang我认为“生成一致的IL”在C#团队的优先级列表中是非常低的。它可能希望这样做来优化IL大小并减少在JIT上花费的时间。不过,这个数字可能还不够高。
        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
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