我看过有关null-coalescing
运算符的推文(右关联):
来自SPEC:
例如,
a ?? b ?? c
形式的表达式被评估为a ?? (b ?? c)
所以还有另一个人回答说可以通过一个例子进行测试和验证:
void Main()
{
Console.WriteLine ((P)null ?? (string)null ?? "b555");
}
public class P
{
public static implicit operator P(string b) {throw new Exception(b??"a");}
}
结果:
Exception: b555
但我并不了解这种行为。
问题
我已经知道??
的非常优先级低但仍然是:
(P)null
应首先评估 (更高优先级)!
但似乎
a ?? (b ?? c)
首先评估。
为什么?
换句话说,似乎这些都是事件:
(P)(null ?? ((string)null ?? "b555"))
然后:
(P)(null ?? "b555")
然后:
(P)"b555"
但我不明白为什么(P)
适用于所有合并表达而不是null
((P)null
}
答案 0 :(得分:3)
为什么要将隐式转化应用于null
中的(P)null
? (P)null
生成一个静态类型为P
的空引用,为什么要在此处应用从字符串转换? (P)null
中没有提及任何字符串。
注意编译器如何静态地键入以下表达式¹:
((string)null ?? "b555") -> string
((P)null ?? ...some expression of type string...) -> P
因此,
((P)null ?? (string)null ?? "b555") -> P
现在可以按如下方式解析表达式:
(P)null
为空,所以我们看一下右侧。
((string)null ?? "b555")
会产生字符串"b555"
(不涉及P)。
((P)null ?? "b555")
会产生"b555"
的值。由于((P)null ?? "b555")
的静态类型为P
,b555
会隐式转换为P
,从而触发您的隐式转化。
正如预期的那样,我们得到了一个例外“b555”。
PS:如果有人对对话形式的更详细解释感兴趣,我们已经将此主题与聊天和here is the transcript进行了对比。
¹证明:
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() {}
}
答案 1 :(得分:1)
(P)
仅适用于第一个null
。但是,类P具有从字符串到P的隐式转换,因此它抛出异常的原因。由于implicit
关键字,它不需要您明确请求类型转换。