0

未来访问者请注意:这个问题是基于错误的复制代码。?.操作员确实短路了。您现在可以关闭此浏览器选项卡。


网上有许多消息来源声称空条件运算符 ( ?.) 短路(例如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 案例,链的其余部分也会执行。链没有中止。对我来说,短路意味着链条被中止。MSDN 声称是这种情况,但代码示例没有演示短路:

//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 开发周期中是否曾经改变过?这将解释网络上的不良来源。如果它不存在,为什么会有这么多关于短路的讨论?我可能在这里误解了一些东西。

不是重复的,因为它是关于操作员是否短路(答案:不,尽管接受的答案没有这么说)。这个候选人是关于可空布尔值和其他无关的。

4

3 回答 3

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?,现在它继续使用.Inner

如果c为 null,则.Inner由于c?..

于 2016-06-24T16:34:55.213 回答
2

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

短路可能发生在每个?.部分,具体取决于哪个部分null。如果obj不是 null 并且第一个Property是则只有其他 2 不会被调用。第二个也一样,以此类推。

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

于 2016-06-24T16:32:45.433 回答
0

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

使用不涉及 null 运算符的示例可能会更清楚。

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

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

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

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

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

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

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

于 2016-06-24T17:36:09.953 回答