Search code examples
c#c#-6.0null-conditional-operator

Null conditional operator and void methods


Before C# 6, I would write code to dispose of an object like:

if (_odbcConnection != null)
{
    _odbcConnection.Close();
    _odbcConnection.Dispose();
    _odbcConnection = null;
}

With 6, I can write much less code:

_odbcConnection?.Close();
_odbcConnection?.Dispose();
_odbcConnection = null;

But are the two equivalent?


Solution

  • Your two lower examples are almost equal. But the second block

    _odbcConnection?.Close();
    _odbcConnection?.Dispose();
    _odbcConnection = null;
    

    will be translated by the compiler to something like

    var tmp1 = _odbcConnection;
    if (tmp1 != null) tmp1.Close();
    var tmp2 = _odbcConnection;
    if (tmp2 != null) tmp2.Dispose();
    _odbcConnection = null;
    

    This means that this version is thread-safe, while the first (with the outer if clause) is not. If some mysterious thread would set _odbcConnection to null after the if but before Close() or Dispose(), a NullReferenceException would be thrown.

    By using the null-conditional-operator you avoid this problem, because the reference is first stored in a compiler generated variable and then checked and used.


    The above translation only applies to fields and properties. For local variables (only in scope of a single method, e.g. method parameters), this translation is not necessary and the code ends up like

    if (_odbcConnection != null) _odbcConnection.Dispose();
    

    That is because local variables cannot be changed by different threads.

    And of course this is only the generated C#. In IL you may not see this anymore as it is either optimized away or obsolete, because in IL the reference value is loaded into a register and then compared. Again, another thread can no longer change that value in the register. So on IL level this discussion is somewhat pointless.