Null-coalescing and right-associative in C # - clarification?

I saw a twitter about null-coalescing

(which is the correct associative one):

From SPEC:

For example, a shape expression a ?? b ?? c

evaluates toa ?? (b ?? c)

So, another guy came along who answered that it can be tested and verified with an example:

void Main()
{
    Console.WriteLine ((P)null ?? (string)null ?? "b555");
}

public class P
{
 public static implicit operator P(string b) {throw new Exception(b??"a");}
}

      

Result:

Exception: b555 

      

But I didn't understand the behavior.

Question

I already know which ??

is of very low priority, but still:

(P)null

must evaluate first (higher priority)!

But it seems that

a ?? (b ?? c)

Evaluated first.

Why?

In other words, it seems that these are events:

 (P)(null ?? ((string)null ?? "b555"))

      

And then:

(P)(null ?? "b555")

      

And then:

(P)"b555"

      

But I don't understand why it (P)

is applied to the whole coalesce expression and not to null

(in (P)null

)

+3


source to share


2 answers


Why should your implicit conversion be applied to null

to (P)null

? (P)null

gives a null reference statically typed on P

, why use any conversion from string here? In (P)null

no mention of one line.

Notice how the compiler statically injects the following expressions:

((string)null ?? "b555")   -> string

((P)null ?? ...some expression of type string...)    -> P

      

Thus,

((P)null ?? (string)null ?? "b555")     -> P

      

The expression can now be solved like this:



  • (P)null

    is null, so we're looking at the right side.

  • ((string)null ?? "b555")

    outputs a string "b555"

    (does not participate in P).

  • ((P)null ?? "b555")

    results in a value "b555"

    . Since the static type ((P)null ?? "b555")

    is equal P

    , it is b555

    implicitly converted to P

    , causing the implicit conversion.

  • We are getting the "b555" exception as expected.

PS: If anyone is interested in a more detailed explanation in the form of a dialogue, we took this topic in the chat, and here is the transcript .


ยน Proof:

public static void Main()
{
    var x = ((P)null ?? "abc");
    x.A();   // compiles
}

public class P
{
    public static implicit operator P(string b) {throw new Exception(b??"a");}
    public void A() {}
}

      

+3


source


(P)

applies only to the first null

. However, class P has an implicit conversion from string to P, which is why it throws an exception. You don't need to explicitly request the type conversion because of the keyword implicit

.



+1


source







All Articles