“零条件运算符短路”是什么意思?

时间:2016-06-24 16:27:50

标签: c# c#-6.0 null-conditional-operator

对未来访问者的注意:此问题基于错误的repro代码。 ?.运算符确实短路。您现在可以关闭此浏览器标签。

网上有很多来源声称空条件运算符(?.)短路(例如http://www.informit.com/articles/article.aspx?p=2421572,搜索“电路”)。我无法发现任何这样的事情:

    static void Main()
    {
        var c = new C();

        Console.WriteLine(c?.Inner?.Inner); //does not rely on short circuiting, works
        Console.WriteLine(c?.Inner.Inner); //throws NullReferenceException
    }

    class C
    {
        public C Inner;
    }

此处,由于第二行?. ,第一行。第二个?.将null视为其第一个操作数,因此也返回null。这不是短路。

显然,即使触发了null case,链的其余部分也会执行。链条没有中止。对我来说,短路意味着链条中止。 MSDN claims this is the case但代码示例并未证明短路:

//The last example demonstrates that the null-condition operators are short-circuiting
int? count = customers?[0]?.Orders?.Count();
// null if customers, the first customer, or Orders is null

在C#6开发周期中,这种行为是否曾经发生过变化?这可以解释网络上的不良消息来源。 为什么会有这么多关于短路的讨论呢?我可能会在这里误解一些东西。

This不是重复的,因为它是关于操作员是否短路(答案:否,尽管接受的答案没有说明)。 This candidate是关于无效的布尔值,否则无关。

3 个答案:

答案 0 :(得分:6)

它确实短路(如果我们的意思是"终止呼叫链)。

考虑以下代码:

using System;

namespace ConsoleApplication1
{
    class C
    {
        public C Inner
        {
            get
            {
                Console.WriteLine("Inner called.");
                return this; // Change this to `return null;`
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var c = new C();

            var x = c?.Inner?.Inner?.Inner;
        }
    }
}

运行它,它将打印

Inner called.
Inner called.
Inner called.

现在将return this;更改为return null;,然后会打印

Inner called.

从而证明调用链在第一个空值处停止。

现在将表达式更改为:

var x = c?.Inner?.Inner.Inner;

它仍会打印

Inner called.

因为它正在被短路。

显然,它必须至少访问一次Inner以查看它是否为空。如果c本身为空,则根本不会访问Inner

请注意,给出表达式:

var x = c?.Inner.Inner;

它会在第一次使用.Inner时给出空引用异常,因为它已使用c检查c?不为空,现在继续使用{{1} }}

如果.Inner为空,则由于c,它根本不会继续访问.Inner

答案 1 :(得分:2)

这里的短路意味着当你有例如obj?.Property1?.Property2?.Property3objnull时,整个表达式返回null并且没有其他属性被调用(因为它们将抛出)。 / p>

每个?.都会发生短路,具体取决于哪个部分为null。如果obj不是空的,而第一个Property则只有其他2个不会被调用。第二个相同,等等。

被短路的是表达式,而不是该表达式之后的其余语句。

答案 2 :(得分:0)

简单来说,短路是一种保证,如果它确定一个属性为空,它就不会继续尝试评估其余属性。

对于不涉及null运算符的示例,可能会更清楚。

在下面的示例中,我们在检查其属性值之前,先检查x是否为null。

if(x != null & x.SomeProperty == 1)

但如果x为空,这仍然会引发异常,因为它会评估这两个条件。即使x为空,它仍然会尝试检查x.SomeProperty并且它会抛出NullReferenceException

但是如果我们使用&&运算符

if(x != null && x.SomeProperty == 1)

然后它"短路。"如果第一个条件不是真的那么它甚至不会评估第二个条件。它正在检查它们是否都是真的。但如果第一个不是真的那么它们都不可能都是真的 - 第二个的价值并不重要。所以它在第一个条件之后停止。

短路最终意味着如果它评估任何使剩余条件无关的东西,则保证不评估剩余条件。