Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 202
TheLethalCoder Avatar asked Jan 05 '23 14:01

TheLethalCoder


1 Answers

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.

like image 99
René Vogt Avatar answered Jan 15 '23 09:01

René Vogt