我对空条件运算符如何与普通属性访问级联感到困惑。举两个例子:
a?.b.c
(a?.b).c
我希望它们是等效的:首先,a?.b
评估 的值,然后result.c
评估。因此,如果a == null
,应该抛出异常。
但是,这只发生在第二个表达式中。第一个表达式的计算结果为null
,这意味着它与 相同a?.b?.c
。为什么?
我对空条件运算符如何与普通属性访问级联感到困惑。举两个例子:
a?.b.c
(a?.b).c
我希望它们是等效的:首先,a?.b
评估 的值,然后result.c
评估。因此,如果a == null
,应该抛出异常。
但是,这只发生在第二个表达式中。第一个表达式的计算结果为null
,这意味着它与 相同a?.b?.c
。为什么?
这只是运算符优先级的问题。让我们来看看案例:
a?.bc
a
=> null
,鉴于null 条件运算符是 short-circuiting ,不会评估其他任何内容。(a?.b).c
a
=>null
返回((B)null).c
=>NullReferenceException
被抛出为了使这些情况相同,您应该进行比较
a?.b.c
(a?.b)?.c
a?.b?.c
(正如你已经提到的)除了 Camilo 已经提供的内容之外,我不知道这是否会有所帮助,但这里有一个简短的比较,显示了在没有空条件运算符的情况下逻辑可能看起来如何。
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; }
}