问号和点运算符是什么?在C#6.0中意味着什么?


359

在VS2015预览版中使用C#6.0,我们有了一个新的运算符,?.可以像这样使用:

public class A {
   string PropertyOfA { get; set; }
}

...

var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
   //somecode
}

它到底是做什么的?

Answers:


499

它是空条件运算符。它基本上意味着:

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

在您的示例中,关键是如果ais nulla?.PropertyOfA则将求值null而不是抛出异常-然后它将与该null引用进行比较foo(使用字符串的==重载),发现它们不相等,执行将进入if语句主体。

换句话说,它是这样的:

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

...除了a只评估一次。

请注意,这也可以更改表达式的类型。例如,考虑FileInfo.Length。那是type的属性long,但是如果将其与null条件运算符一起使用,则最终会得到type的表达式long?

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

8
它不是称为空条件运算符吗?
SLaks'2

1
@SLaks:我以为它是“条件空”,但我可能是错的。上次查看Roslyn语言功能文档时,它没有被重命名。也许来源是这里的权限-将进行检查。
乔恩·斯基特

3
@SLaks:好的。在SyntaxKind中,显然是ConditionalAccessExpression,这两个都不是很烦人……
Jon Skeet

12
我更喜欢“ Elvis”运算符的名称:P
Ahmed ilyas,​​2015年

3
仅作记录,我已经为该操作符看到了五个不同的名称:安全导航,空条件,空传播,条件访问,猫王。
Gigi

81

展平层次结构和/或映射对象时,它非常有用。代替:

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工作示例

??或null推算运算符不同于?或null条件运算符)。

也可以将其与Action一起用于赋值运算符。代替

Action<TValue> myAction = null;

if (myAction != null)
{
  myAction(TValue);
}

可以简化为:

myAction?.Invoke(TValue);

DotNetFiddle示例

使用系统;

public class Program
{
  public static void Main()
  {
    Action<string> consoleWrite = null;

    consoleWrite?.Invoke("Test 1");

    consoleWrite = (s) => Console.WriteLine(s);

    consoleWrite?.Invoke("Test 2");
  }
}

结果:

测试2


27
为了拯救人们仰望什么?is ..它是null-coalescing运算符,如果不为null,则将返回Name,否则将返回“ N / A”。
史蒂夫(Steve)

6
@Erik飞利浦我认为你需要添加 || Model.Model2.Model3.Model4.Name == null 具有相同的逻辑,否则情况Model.Model2.Model3.Model4.Namenullmapped.Name将留null
RazvanR

2
@ErikPhilips我猜不在同一页面上。如果Model.Model2.Model3.Model4.Name是,请尝试查看两种情况下会发生什么null
RazvanR

1
结果为“ N / A”,请再次阅读第一条评论。 DotNetFiddle.Net工作示例
艾里克·飞利浦

7
@ErikPhilips:与第一个评论无关,因为这与您的第一个示例无关。在此示例中,您将跳入else-branch并拥有mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null,而第二个示例将替换为mapped.Name = "N/A"。参见编辑过的DotNetFiddle
derM,2015年

3

这对于C#来说是相对较新的,这使我们可以轻松地在方法链中针对null或非null值调用函数。

实现相同目的的旧方法是:

var functionCaller = this.member;
if (functionCaller!= null)
    functionCaller.someFunction(var someParam);

现在,通过以下操作,它变得更加容易:

member?.someFunction(var someParam);

我强烈建议您在这里阅读:

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/null-conditional-operators

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.