2015-02-05 54 views

回答

219

这是null conditional运营商。它基本上表示:

“评估第一个操作数;如果它为null,则停止,结果为null;否则,评估第二个操作数(作为第一个操作数的成员访问)。

在您的例子,问题是,如果anull,然后a?.PropertyOfA将评估为null而不是抛出一个异常 - 那么它会比较的是null参考与foo(使用string的==过载),发现他们不是平等和执行将进入if声明的正文。

换句话说,它是这样的:

string bar = (a == null ? null : a.PropertyOfA); 
if (bar != foo) 
{ 
    ... 
} 

...除了a只计算一次。

请注意,这也可以更改表达式的类型。例如,考虑FileInfo.Length。这是long类型的属性,但是如果与空条件运算符使用它,你最终long?类型的表达式:

FileInfo fi = ...; // fi could be null 
long? length = fi?.Length; // If fi is null, length will be null 
+4

是不是所谓的_null conditional_操作符? – SLaks 2015-02-05 19:14:34

+1

@SLaks:我认为这是“有条件的空”,但我可能是错的。上次我查看Roslyn语言功能文档时,它没有被重命名为。也许来源是这里的权威 - 将检查。 – 2015-02-05 19:16:00

+0

“有条件的空”使它听起来像是一种空,它不是。 – SLaks 2015-02-05 19:19:00

28

扁平化层级和/或映射对象时,它可以是非常有用的。代替:

if (Model.Model2 == null 
    || Model.Model2.Model3 == null 
    || Model.Model2.Model3.Model4 == null 
    || Model.Model2.Model3.Model4.Name == null) 
{ 
    mapped.Name = "N/A" 
} 
else 
{ 
    mapped.Name = Model.Model2.Model3.Model4.Name; 
} 

它可以写成像(如上相同的逻辑)

mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A"; 

DotNetFiddle.Net Working Example

+14

为了节省人们看什么?是..它是空合并运算符,如果它不为null,将返回Name,否则将返回“N/A”。 – Steve 2017-03-05 01:09:53

+2

@Erik Philips我认为您需要添加 **'|| Model.Model2.Model3.Model4.Name == null' ** 具有相同的逻辑,否则如果'Model.Model2.Model3.Model4.Name'为'null','mapped.Name'将保持' null' – RazvanR 2017-06-08 07:38:01

+0

@RazvanR请阅读关于??的以前的评论。 – 2017-06-08 21:42:42