1

I have a condition

if (driver?.VistrackId == 555)

it equivalent (in IL code, not C# code):

if (driver != null && driver.VistrackId == 555)

right?

Oleg Sh
  • 8,496
  • 17
  • 89
  • 159

3 Answers3

4

Not exactly

It's better Since this notation is thread safe

See Null-conditional Operators on MSDN.

Alexey Klipilin
  • 1,866
  • 13
  • 29
  • I think the thread-safety in the article is directed towards handling delegates, not necessarily towards handling variables. It depends on the situation if it is actually thread-safe. See [this answer](https://stackoverflow.com/a/35786442/9239792) for a discussion on the thread-safety of the operator. – RMH Mar 10 '18 at 13:36
  • @RMH but as I understand this operation is kind of atomic, and you can't set `null` your variable during null propagation is processed, even you set object to `null` you still be referencing initial object – Alexey Klipilin Mar 10 '18 at 13:59
  • my apologies, I misinterpreted your meaning (and the doc's) of 'thread safe' here. I agree that the variable cannot become null during its null-check exactly as you stated. In that sense it is a 'thread-safe null-check'. However, this does not hold for the called property / method (`VistrackId` in the post's case). – RMH Mar 10 '18 at 14:45
2

That's correct. The "?" checks for null, and if it's not null, the "." continues the interrogation of the object

baileyrt
  • 626
  • 7
  • 13
1

This code generates the following IL

var driver = new {VistrackId = 1};

if (driver?.VistrackId == 555)
{
    Console.WriteLine("?. operator");
}

IL:

IL_0000:  nop         
IL_0001:  ldc.i4.1    
IL_0002:  newobj      <>f__AnonymousType0<System.Int32>..ctor
IL_0007:  stloc.0     // driver
IL_0008:  ldloc.0     // driver
IL_0009:  brtrue.s    IL_000E
IL_000B:  ldc.i4.0    
IL_000C:  br.s        IL_001B
IL_000E:  ldloc.0     // driver
IL_000F:  call        <>f__AnonymousType0<System.Int32>.get_VistrackId
IL_0014:  ldc.i4      2B 02 00 00 
IL_0019:  ceq         
IL_001B:  stloc.1     
IL_001C:  ldloc.1     
IL_001D:  brfalse.s   IL_002C
IL_001F:  nop         
IL_0020:  ldstr       "?. operator"
IL_0025:  call        System.Console.WriteLine
IL_002A:  nop         
IL_002B:  nop         
IL_002C:  ret    

Code with == null

var driver = new {VistrackId = 1};


if (driver != null && driver.VistrackId == 555)
{
    Console.WriteLine("== null");
}

IL

IL_0000:  nop         
IL_0001:  ldc.i4.1    
IL_0002:  newobj      <>f__AnonymousType0<System.Int32>..ctor
IL_0007:  stloc.0     // driver
IL_0008:  ldloc.0     // driver
IL_0009:  brfalse.s   IL_001A
IL_000B:  ldloc.0     // driver
IL_000C:  callvirt    <>f__AnonymousType0<System.Int32>.get_VistrackId
IL_0011:  ldc.i4      2B 02 00 00 
IL_0016:  ceq         
IL_0018:  br.s        IL_001B
IL_001A:  ldc.i4.0    
IL_001B:  stloc.1     
IL_001C:  ldloc.1     
IL_001D:  brfalse.s   IL_002C
IL_001F:  nop         
IL_0020:  ldstr       "== null"
IL_0025:  call        System.Console.WriteLine
IL_002A:  nop         
IL_002B:  nop         
IL_002C:  ret         

They are slightly different

Reuel Ribeiro
  • 1,419
  • 14
  • 23