成员访问运算符(。)的优先级是否高于空条件成员访问运算符(?。)的优先级?

时间:2018-09-27 11:35:58

标签: c# .net

我认为我们都同意C#6.0中引入的空条件成员访问运算符?.非常方便。

但是我一直想知道一件事。给出以下代码:

using System.Collections.Generic;

public class MyClass
{
    public void DoSomething(Foo foo)
    {
        var knownIndices = new[] { 42 };
        bool overlaps;

        // might throw a null reference exception
        overlaps = foo.Indices.Overlaps(knownIndices);

        // how I used to do it
        overlaps = foo != null && foo.Indices != null && foo.Indices.Overlaps(knownIndices);

        // with null conditional member access (won't compile)
        //overlaps = foo?.Indices?.Overlaps(knownIndices).GetValueOrDefault();

        // with null conditional member access (using local variable)
        bool? overlapsOrIsIndeterminable = foo?.Indices?.Overlaps(knownIndices);
        overlaps = overlapsOrIsIndeterminable.GetValueOrDefault();

        // with null conditional member access (inlined)
        overlaps = (foo?.Indices?.Overlaps(knownIndices)).GetValueOrDefault();

        // with null conditional member access and null-coalescing
        overlaps = foo?.Indices?.Overlaps(knownIndices) ?? false;
    }

    public class Foo
    {
        public HashSet<int> Indices;
    }
}

为什么在链接表达式中必须使用括号?正如我们在示例中使用局部变量所见,?.Overlaps()显然评估为可为空的布尔值,因此我希望.GetValueOrDefault()是可编译的。

The C# language reference指出成员访问运算符.和空条件成员访问运算符?.都是主要运算符,因此共享相同的优先级。

.尽管在语言参考中有规定,但其优先级是否高于?.

2 个答案:

答案 0 :(得分:3)

  

是。尽管语言参考中有说明,但优先级比?。?

空条件运算符是一种特殊情况。就像Dave解释的那样,如果?.运算符右边的任何连续表达式都不为null,则不会对其进行求值。如果包含?.运算符的整个表达式的结果通常将评估为原始值(例如int),则它将实际上评估为Nullable<int>值,但该值不适用于操作员的右侧。在运算符的右边,您可以假定该值不为null(这是空条件运算符的功效)。

虽然foo.GetIntValue()返回int,但是foo?.GetIntValue()返回Nullable<int>。如果附加到此表达式,则“目标”值的类型为int,而不是Nullable<int>。因此,以下代码无法编译,因为GetValueOrDefaultNullable<int>的成员,而不是int的成员。

foo?.GetIntValue().GetValueOrDefault(); // ERROR

由于 entire 表达式的计算结果为Nullable<int>,因此添加方括号确实可以调用GetValueOrDefault

(foo?.GetIntValue()).GetValueOrDefault();

请注意,您可以将此操作符与null-coalescing operator

无缝组合
foo?.GetIntValue() ?? 1; // If foo is null, this expression will evaluate to 1

答案 1 :(得分:2)

来自https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

空条件运算符正在短路。如果条件成员访问和索引操作链中的一个操作返回null,则链中其余部分的执行将停止。在下面的示例中,如果A,B或C的值为空,则E不执行。

C#

复制 A?.B?.C?.Do(E); A?.B?.C?[E];