简体   繁体   English

为什么空条件运算符会更改常规属性访问?

[英]Why does the null-conditional operator change regular property access?

I'm confused about how the null-conditional operator cascades with normal property access. 我很困惑null条件运算符如何与普通属性访问级联。 Take these two examples: 拿这两个例子:

a?.b.c
(a?.b).c

I would expect them to be equivalent: first, the value of a?.b is evaluated, then result.c is evaluated. 我希望它们是等价的:首先,评估a?.b的值,然后评估result.c Thus if a == null , an exception should be thrown. 因此,如果a == null ,则应抛出异常。

However, that only happens in the second expression. 但是,这只发生在第二个表达式中。 The first expression evaluates to null , meaning it's the same as a?.b?.c . 第一个表达式的计算结果为null ,这意味着它与a?.b?.c Why? 为什么?

That's only a matter of operator precedence. 这只是运营商优先权的问题。 Let's go through the cases: 让我们来看看案例:

a?.bc 一个?.BC

  1. Evaluate a => null is returned, nothing else is evaluated given that the null-conditional operators are short-circuiting . 返回评估a => null ,假设空条件运算符短路,则不评估任何其他值。

(a?.b).c (一?.B).C

  1. Evaluate a => null is returned 评估a => null返回
  2. Evaluate ((B)null).c => NullReferenceException is thrown Evaluate ((B)null).c =>抛出NullReferenceException

For these cases to be equivalent, you should be comparing 对于这些相同的情况,您应该进行比较

  1. a?.bc
  2. (a?.b)?.c
  3. a?.b?.c (as you already mentioned) a?.b?.c (如你所说)

I don't know if this'll help or not, beyond what Camilo already provided, but here's a brief comparison showing how the logic might look without the null-conditional operator in play. 我不知道这是否有所帮助,超出了Camilo已经提供的内容,但是这里有一个简短的比较,显示逻辑在没有空条件运算符的情况下可能看起来如何。

public class Program
{
    public static void Main()
    {
        A a;

        a = new A { b = new B { c = 5 } };

        Console.WriteLine(a?.b.c);        // returns 5;
        Console.WriteLine((a?.b).c);      // returns 5;

        a = null;

        Console.WriteLine(a?.b.c ?? -1);  // returns -1;
        Console.WriteLine((a?.b).c);      // throws NullReferenceException


        // Similar to a?.b.c

        if (a != null)
            Console.WriteLine(a.b.c);     // returns 5;
        else
            Console.WriteLine(-1);        // returns -1;


        // Similar to (a?.b).c

        B tmp;
        if (a != null)
            tmp = a.b;
        else
            tmp = null;

        Console.WriteLine(tmp.c);         // returns 5 or throws NullReferenceException
    }
}


public class A
{
    public B b { get; set; }
}

public class B
{
    public int c { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM