"the null conditional operator short circuits" 是什么意思?

What is meant by "the null conditional operator short circuits"?

未来访客请注意:这个问题是基于错误的重现代码。 ?. 运算符确实短路了。您现在可以关闭此浏览器选项卡。


网络上有许多来源声称空条件运算符 (?.) 短路(例如 http://www.informit.com/articles/article.aspx?p=2421572,搜索 "circuit")。我无法检测到任何此类内容:

    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 情况,链的其余部分也会执行。链没有中止。对我来说,短路意味着链条中止。 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 开发周期中是否发生过更改?这可以解释网络上的不良来源。 如果不存在短路,为什么会有那么多关于短路的讨论?我可能在这里误解了什么。

is not a duplicate because it's about whether the operator short circuits or not (answer: no, although the accepted answer does not say that). This candidate 是关于可为空的布尔值,否则不相关。

这里的短路意味着当你有例如 obj?.Property1?.Property2?.Property3 并且 objnull 那么整个表达式 returns null 并且没有其他属性被调用(因为他们会扔)。

每个 ?. 都可能发生短路,具体取决于哪个部分是 null。如果 obj 不为空且第一个 Property 为空,则不会调用其他 2 个。第二个相同,依此类推。

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

它会短路(如果我们的意思是“终止调用链”)。

考虑这段代码:

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.

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

现在将表达式更改为:

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

它仍然会打印

Inner called.

因为短路了

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

注意给定表达式:

var x = c?.Inner.Inner;

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

如果 c 为 null,它根本不会继续访问 .Inner,因为 c?..

简而言之,短路是一种保证,如果它确定一个 属性 为空,它就不会继续尝试评估其余部分。

用一个不涉及 null 运算符的例子可能会更清楚。

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

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

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

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

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

然后 "short circuits." 如果第一个条件不成立,它甚至不会评估第二个条件。它正在检查它们是否都是真的。但是,如果第一个不正确,那么它们不可能都为真——第二个的值无关紧要。所以它在第一个条件后停止。

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