Consider the following code, which uses two slightly different methods to check _instance
and assign it when not already set.
class InstantiationTest
{
private Object _instance;
public void Method1() {
if(_instance == null) {
_instance = new Object();
}
}
public void Method2() {
_instance = _instance ?? new Object();
}
}
Either VS or Resharper keeps underlining my explicit null checks, and prompting me to refactor using the null-coalescing operator.
I wondered whether the compiler is smart enough to detect the case in Method2()
where _instance
is reassigned to itself (effectively a nop?) and rewrite Method2()
into Method1()
.
I see this is not actually the case:
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
versus:
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
My question is why?
Is it tricky to implement at the compiler level, too trivial to be worth the effort of implementation, or something I'm missing?
Generally, the C# compiler does very little optimizing of the IL, leaving that up to the JIT, which optimizes things much better for a specific architecture. So it's simply not been implemented within the compiler, as that would take time away from other things.