编译器对显式空检查与空合并操作符的求值

本文关键字:操作符 合并 检查 编译器 | 更新日期: 2023-09-27 18:15:06

考虑下面的代码,它使用两个稍微不同的方法来检查_instance并在尚未设置时分配它。

class InstantiationTest
{
    private Object _instance;
    public void Method1() {
        if(_instance == null) {
            _instance = new Object();
        }
    }
    public void Method2() {
        _instance = _instance ?? new Object();
    }
}

VS或Resharper一直强调我的显式空检查,并提示我使用空合并操作符进行重构。

我想知道编译器是否足够聪明,以检测Method2()_instance被重新分配给自身的情况(有效地nop?)并将Method2()重写为Method1()

我看到实际上不是这样的:

Test.Method1:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery+Test._instance
IL_0006:  brtrue.s    IL_0013
IL_0008:  ldarg.0     
IL_0009:  newobj      System.Object..ctor
IL_000E:  stfld       UserQuery+Test._instance
IL_0013:  ret   

Test.Method2:
IL_0000:  ldarg.0     
IL_0001:  ldarg.0     
IL_0002:  ldfld       UserQuery+Test._instance
IL_0007:  dup         
IL_0008:  brtrue.s    IL_0010
IL_000A:  pop         
IL_000B:  newobj      System.Object..ctor
IL_0010:  stfld       UserQuery+Test._instance
IL_0015:  ret      

我的问题是为什么?

在编译器级别实现是否很棘手,太琐碎而不值得实现,或者我错过了什么?

编译器对显式空检查与空合并操作符的求值

一般来说,c#编译器很少对IL进行优化,将其留给JIT,后者针对特定的体系结构优化得更好。所以它只是没有在编译器中实现,因为这会占用其他事情的时间。