What is meant by “the null conditional operator short circuits”?

只谈情不闲聊 提交于 2019-12-31 05:15:31

问题


Note to future visitors: This question was based on faulty repro code. The ?. operator does indeed short circuit. You can close this browser tab now.


There are many sources on the web that claim that the null conditional operator (?.) short circuits (e.g. http://www.informit.com/articles/article.aspx?p=2421572, search for "circuit"). I cannot detect any such thing:

    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;
    }

Here, the first line works because of the second ?.. The second ?. saw null as its first operand and therefore returned null as well. This is not short circuiting.

Apparently, the rest of the chain executes even if the null case was triggered. The chain is not aborted. To me, short circuiting means that the chain is aborted. MSDN claims this is the case but the code example does not demonstrate short circuiting:

//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

Was this behavior ever changed during the C# 6 development cycle? That would explain the bad sources on the web. And why is there so much talk about short circuiting if it's not there? I might be misunderstanding something here.

This 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 is about nullable booleans and otherwise unrelated.


回答1:


It does short-circuit (if by that we mean "terminate the chain of calls).

Consider this code:

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;
        }
    }
}

Run that and it will print

Inner called.
Inner called.
Inner called.

Now change return this; to return null;, and it will print

Inner called.

thus demonstrating that the call chain was stopped at the first null.

Now change the expression to:

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

and it will still print

Inner called.

because it is being short circuited.

Obviously it has to access Inner at least once to see if it is null. If c itself is null, then Inner isn't accessed at all.

Note that given the expression:

var x = c?.Inner.Inner;

it will give a null reference exception at the first use of .Inner because it has already checked that c is not null using c? and now it goes on to use .Inner.

If c was null, it would not have proceeded to access .Inner at all because of the c?..




回答2:


Short circuit here means that when you have for example obj?.Property1?.Property2?.Property3 and obj is null then the whole expression returns null and no other properties are called (as they will throw).

That short circuiting can happen on each ?. depending on which part is null. if obj isn't null and the first Property is then only the other 2 won't be called. Same for the second and so forth.

The thing being short circuited is the expression, not the rest of the statements after that expression.




回答3:


In real simple terms, short-circuiting is a guarantee that if it determines that one property is null, it's not going to keep trying to evaluate the rest.

It might be clearer with an example that doesn't involve the null operator.

In the example below, we're checking to see if x is null before checking the value of its property.

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

But this is still going to throw an exception if x is null because it's going to evaluate both conditions. Even if x is null it's still going to try to check x.SomeProperty and it's going to throw a NullReferenceException.

But if we use the && operator instead

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

Then it "short circuits." If the first condition isn't true then it won't even evaluate the second condition. It's checking to see if they are both true. But if the first one isn't true then there's no way they can both be true - the value of the second one doesn't matter. So it stops after the first condition.

Short circuiting eventually means that if it evaluates anything that renders the remaining conditions irrelevant then it is guaranteed not to evaluate the remaining conditions.



来源:https://stackoverflow.com/questions/38018083/what-is-meant-by-the-null-conditional-operator-short-circuits

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!