空条件运算符和void方法

时间:2017-02-07 15:12:05

标签: c# c#-6.0 null-conditional-operator

在C#6之前,我会编写代码来处理像:

这样的对象
if (_odbcConnection != null)
{
    _odbcConnection.Close();
    _odbcConnection.Dispose();
    _odbcConnection = null;
}

使用6我可以编写更少的代码:

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

但两者是否相同?

1 个答案:

答案 0 :(得分:6)

你的两个较低的例子几乎相等。但第二块

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

将由编译器翻译为类似

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

这意味着此版本是线程安全的,而第一个版本(使用外部if子句)则不是。如果某个神秘线程在_odbcConnection之后nullif之后将Close()设置为Dispose(),则会抛出NullReferenceException

通过使用null-conditional-operator可以避免这个问题,因为引用首先存储在编译器生成的变量中,然后进行检查和使用。

以上翻译仅适用于字段和属性。对于局部变量(仅在单个方法的范围内,例如方法参数),此翻译不是必需的,代码最终会像

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

这是因为不同的线程无法更改局部变量。

当然这只是生成的C#。在IL中,您可能不会再看到它,因为它被优化掉或过时,因为在IL中,参考值被加载到寄存器中然后进行比较。同样,另一个线程不能再在寄存器中更改该值。所以在IL级别上,这种讨论有点毫无意义。