Оценка компилятором явного нуль-проверки против оператора нуль-слияния? - PullRequest
4 голосов
/ 16 ноября 2011

Рассмотрим следующий код, который использует два слегка различных метода для проверки _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      

У меня вопрос почему ?

Это сложно реализовать на уровне компилятора, слишком тривиально, чтобы стоить усилий по реализации, или я чего-то упускаю?

1 Ответ

5 голосов
/ 16 ноября 2011

Как правило, компилятор C # очень мало оптимизирует IL, оставляя это на усмотрение JIT, что оптимизирует вещи намного лучше для конкретной архитектуры.Так что он просто не реализован в компиляторе, так как это отнимает время у других вещей.

...