I'm confused about how the null-conditional operator cascades with normal property access. Take these two examples:
a?.b.c
(a?.b).c
I would expect them to be equivalent: first, the value of a?.b
is evaluated, then result.c
is evaluated. Thus if a == null
, an exception should be thrown.
However, that only happens in the second expression. The first expression evaluates to null
, meaning it's the same as a?.b?.c
. Why?
That's only a matter of operator precedence. Let's go through the cases:
a?.b.c
a
=> null
is returned, nothing else is evaluated given that the null-conditional operators are short-circuiting.(a?.b).c
a
=> null
is returned((B)null).c
=> NullReferenceException
is thrownFor these cases to be equivalent, you should be comparing
a?.b.c
(a?.b)?.c
a?.b?.c
(as you already mentioned)I don't know if this'll help or not, beyond what Camilo already provided, but here's a brief comparison showing how the logic might look without the null-conditional operator in play.
public class Program
{
public static void Main()
{
A a;
a = new A { b = new B { c = 5 } };
Console.WriteLine(a?.b.c); // returns 5;
Console.WriteLine((a?.b).c); // returns 5;
a = null;
Console.WriteLine(a?.b.c ?? -1); // returns -1;
Console.WriteLine((a?.b).c); // throws NullReferenceException
// Similar to a?.b.c
if (a != null)
Console.WriteLine(a.b.c); // returns 5;
else
Console.WriteLine(-1); // returns -1;
// Similar to (a?.b).c
B tmp;
if (a != null)
tmp = a.b;
else
tmp = null;
Console.WriteLine(tmp.c); // returns 5 or throws NullReferenceException
}
}
public class A
{
public B b { get; set; }
}
public class B
{
public int c { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With