奇怪的操作符优先级与 ??(空值合并运算符)
奇怪的操作符优先级与 ??(空值合并运算符)
最近我遇到了一个奇怪的错误,我在一个int?
与一个字符串进行拼接,然后在此之后再添加另一个字符串。
我的代码基本上相当于这样:
int? x=10; string s = "foo" + x ?? 0 + "bar";
令人惊讶的是,这段代码可以运行和编译,而且不会出现警告或不兼容的类型错误,这段代码也是如此:
int? x=10; string s = "foo" + x ?? "0" + "bar";
然而,这段代码会导致意外的类型不兼容错误:
int? x=10; string s = "foo" + x ?? 0 + 12;
这个更简单的例子也是如此:
int? x=10; string s = "foo" + x ?? 0;
有人可以解释一下这是如何工作的吗?
空合并运算符(null coalescing operator)的优先级非常低,所以您的代码被解释为:
int? x = 10; string s = ("foo" + x) ?? (0 + "bar");
在这个例子中,两个表达式都是字符串,所以它可以编译,但不会产生您期望的结果。在您的下一个例子中,空合并运算符的左侧是一个字符串,但右侧是一个整数,所以它无法编译:
int? x = 10; string s = ("foo" + x) ?? (0 + 12); // 错误:无法将运算符“??”应用于类型为“string”和“int”的操作数
解决方法当然是添加括号:
int? x = 10; string s = "foo" + (x ?? 0) + "bar";
啊,因为优先级很低,所以两边几乎形成了两个独立的表达式,这就解释了为什么int x = 10; string s = "foo" + x ?? "0";
能工作。
Weird operator precedence with ?? (null coalescing operator) 问题的出现的原因是 ?? 运算符的优先级低于 + 运算符。因此,表达式实际上按照以下方式工作:
string s = ("foo" + x) ?? (0 + "bar");
首先,将字符串 "foo" 和变量 x 的字符串值进行连接,如果这个结果是 null(实际上不可能是 null),则将数字 0 的字符串值和字符串 "bar" 进行连接。
解决方法是使用括号来明确指定运算顺序,将 ?? 运算符的优先级提高到 + 运算符之上。以下是解决方法的示例代码:
string s = (("foo" + x) ?? 0) + "bar";
通过在括号中将 ?? 运算符与其操作数包裹起来,我们确保先进行 ?? 运算,然后再进行 + 运算。这样,当连接操作的结果为 null 时,我们将得到字符串 "0bar",而不是 "bar"。