Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the Null-Conditional operator optimized across consecutive usages sites or does it result in duplicate checks?

Tags:

c#

c#-6.0

Does using the null-conditional operator duplicate null checks? For example

var x = instance?.Property1;
var y = instance?.Property2;

Does that get compiled into this:

if (instance != null)
{
  var x = instance.Property1;
  var y = instance.Property2;
}

Or this?

if (instance != null)
{
  var x = instance.Property1;
}

if (instance != null)
{
  var y = instance.Property2;
}

If the former, does it make a difference if there is other code in between both lines? In other words, how smart is the compiler/optimizer?

like image 467
Nelson Rothermel Avatar asked Jan 25 '16 03:01

Nelson Rothermel


1 Answers

The compiler appears to be quite ignorant of this.

The code:

var x = instance?.Property1;
var y = instance?.Property2;

...compiles as non-optimized to:

IL_0000:  nop         
IL_0001:  newobj      UserQuery+Class..ctor
IL_0006:  stloc.0     // instance
IL_0007:  ldloc.0     // instance
IL_0008:  brtrue.s    IL_000D
IL_000A:  ldnull      
IL_000B:  br.s        IL_0013
IL_000D:  ldloc.0     // instance
IL_000E:  ldfld       UserQuery+Class.Property1
IL_0013:  stloc.1     // x
IL_0014:  ldloc.0     // instance
IL_0015:  brtrue.s    IL_001A
IL_0017:  ldnull      
IL_0018:  br.s        IL_0020
IL_001A:  ldloc.0     // instance
IL_001B:  ldfld       UserQuery+Class.Property2
IL_0020:  stloc.2     // y
IL_0021:  ret         

Class..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  nop         
IL_0007:  ret         

...and to optimized as:

IL_0000:  newobj      UserQuery+Class..ctor
IL_0005:  dup         
IL_0006:  dup         
IL_0007:  brtrue.s    IL_000C
IL_0009:  pop         
IL_000A:  br.s        IL_0012
IL_000C:  ldfld       UserQuery+Class.Property1
IL_0011:  pop         
IL_0012:  dup         
IL_0013:  brtrue.s    IL_0017
IL_0015:  pop         
IL_0016:  ret         
IL_0017:  ldfld       UserQuery+Class.Property2
IL_001C:  pop         
IL_001D:  ret         

Class..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  ret         

Both clearly with two branch checks.

like image 53
Enigmativity Avatar answered Sep 27 '22 18:09

Enigmativity