空条件运算符

Null-Conditional Operator

var a = b?.c.d;

这个表达式不应该总是给出编译错误吗?如果 b 为 null,则通过 null 值传播,因此 c 也将为 null,因此也需要此运算符。据我了解,在表达式中使用此运算符传播病毒。

但是 Visual Studio 2015 和 Resharper 都没有对我说什么,我是不是漏掉了什么?

运算符只是语法糖:

MyType a = b == null ? 
    null: 
    b.c.d;

我不清楚为什么这会引发编译错误。

If b is null, the null value is propagated through so c will also be null and thus also need this operator

这不是真的。实际上,当 b 为空时,c 甚至不存在,因为没有该成员可以存在的实例。所以简而言之,运算符只是 returns null 并且省略了 c 甚至 d 的进一步评估。

此运算符短路并且 returns null 如果 bnull

var a = b == null ? null : b.c.d

这就是该语句以旧方式看起来的样子,?. 运算符在它之前的内容为 null 时不会看得更深,它只是 returns null,但是你会在定义 bb.c == null 的地方出现错误,因为你没有写成 var a = b?.c?.d.

注意:

var a1 = b?.c.d;

完全不同于:

var a2 = (b?.c).d;

简而言之,要解释一元运算符 ?. 的工作原理并不是很容易(是的,一元!)。但想法是,如果 ?. 之前的表达式为空,则跳过 "operations" 的 "chain" 的其余部分。

所以对于 a1,每当 b 时,您都会得到成员 d 携带的编译时类型的空值(或 Nullable<>,如果需要的话)恰好为空。当 b 恰好为非空时,您将得到与 b.c.d 相同的结果,如果 b.c 为空,则可能会失败。

但是a2就完全不同了。如果 b 为空,它总是会爆炸,因为括号 (b?.c) 将是一个空引用,而下一个 . 运算符将导致 NullReferenceException。 (我在这里假设 c 在编译时有一个引用类型。)

所以不要认为有一种"left-associativity"使得b?.c.d等同于(b?.c).d


您可以在 中找到初步 C# 语言规范的 link;他们在 § 7.7.1.

中提到 Null-conditional operator 作为一元运算符