空值条件运算符

4

var a = b?.c.d;

这个表达式不应该总是会出现编译错误吗?如果b为null,则null值会传播,因此c也将为null,并且还需要使用此运算符。在我的理解中,表达式中使用此运算符会产生传染性。

但是,无论是Visual Studio 2015还是Resharper都没有提示任何信息,我是否漏掉了什么?


1
不,如果b已经是null,c根本不会被评估,使得a变成了简单的null - MakePeaceGreatAgain
我不理解这个问题;如果bnull,那么表达式不会再被评估,但会产生null,所以c不会受到任何影响。 - Codor
你期望会生成哪种编译器错误? - Servy
1
你是不是想到了 var a = (b?.c).d; 这个代码? - Damien_The_Unbeliever
@Damien_The_Unbeliever 这也能编译。 - Servy
显示剩余6条评论
4个回答

4
这个操作符只是语法糖,实际上它的意思等同于这个表达式:
MyType a = b == null ? 
    null: 
    b.c.d;

我不清楚为什么这会导致编译错误。

如果 b 为 null,则 null 值会通过,因此 c 也将为 null,并且因此需要此运算符。

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


这不是一个有效的转换。无论如何,a总是被赋予一个新值,尽管这个值可能是null - Servy
var a = (b == null) ? null : b.c.d; - Jeroen van Langen
2
还要注意的是,b并没有被多次计算,所以你的语法糖也不正确,尽管现在更接近了。 - Servy
@Servy 最新评论的一个例子可以是:如果 b 被定义为以下内容:class CurrentClass { static bool wasCalledBefore; static B { get { if(wasCalledBefore) { return null; } wasCalledBefore = true; return new B { c = new C { d = new D(), }, }; } } } - Jeppe Stig Nielsen

0
请注意:
var a1 = b?.c.d;

与之完全不同:

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

很难简短地解释一元运算符?.的工作原理(是的,一元的!)。但是它的思想是,如果?.之前的表达式为null,则“操作”链的其余部分都会被跳过。

因此对于a1,每当b恰好为null时,您将得到由成员d(或必要时该类型的Nullable<>)携带的编译时类型的null。当b非null时,您将得到与b.c.d相同的结果,如果b.c为null可能会失败。

但是a2则完全不同。如果b为null,则它将始终崩溃,因为括号(b?.c)将是一个null引用,接下来的.运算符将导致NullReferenceException。(我在这里假设c在编译时具有引用类型。)

因此,请不要认为存在一种“左关联性”,使b?.c.d等价于(b?.c).d


您可以在另一个线程的此答案中找到初步的C#语言规范链接;它们在§ 7.7.1中将Null-conditional operator作为一元运算符进行了提及。


0

这个运算符进行短路操作,如果 bnull,则返回 null


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

这是旧方式中该语句的样子,?. 操作符在它前面的内容为 null 时不会继续往下查找,而是直接返回 null。但是当 b 被定义且 b.c == null 时,如果你没有按照 var a = b?.c?.d 的方式编写,你将会遇到错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接