C#空条件/空合并运算符预编译异常?是Bug还是我理解有误?
C# 中 null 条件运算符、空合并运算符与逻辑或运算符的优先级陷阱
问题重现
以下代码运行后无任何输出,但预期应该输出数组中的所有元素(因为s == x.S的结果为true,满足逻辑或的任一条件):
using System.Collections.Generic; using System; public class Program { static void Main (string[] args) { string[] arr = new[] { "a","b","c"}; string s = "y3"; X x = new X(); foreach(string a in arr) { if(x.Y?.Contains(a) ?? false || s == x.S) { Console.WriteLine(a); } } } } public class X { public string S = "y3"; public List<string> Y = new(){ "y1", "y2" }; }
仅给x.Y?.Contains(a) ?? false添加括号后,代码即可正常输出所有元素:
if((x.Y?.Contains(a) ?? false) || s == x.S)
原因分析
核心问题是C#运算符的优先级:
- 空合并运算符
??的优先级高于逻辑或运算符|| - 原表达式
x.Y?.Contains(a) ?? false || s == x.S会被编译器解析为:x.Y?.Contains(a) ?? (false || s == x.S)
结合代码中的实际值分析错误逻辑:
x.Y不为null,所以x.Y?.Contains(a)会执行Contains方法,返回false(因为a的值是"a"/"b"/"c",都不在Y的元素中)- 计算右侧的
false || s == x.S,由于s == x.S为true,所以这部分结果是true - 整个表达式变为
false ?? true,空合并运算符会取左侧的非null值false,因此整个if条件不成立,无输出
而添加括号后,表达式被强制解析为预期的逻辑:
((x.Y?.Contains(a) ?? false) || s == x.S)
此时先判断x.Y?.Contains(a) ?? false得到false,再与s == x.S的true做逻辑或,结果为true,触发输出。
解决方案
通过添加显式括号,明确指定运算顺序,确保空合并运算的结果先与逻辑或运算结合,而非逻辑或运算先参与空合并的右侧表达式计算。
总结
这是典型的运算符优先级陷阱,??的优先级高于||和&&等逻辑运算符,在混合使用这些运算符时,必须通过显式括号明确代码的逻辑意图,避免编译器按照默认优先级解析出不符合预期的逻辑。
内容的提问来源于stack exchange,提问作者Griswald_911
相关产品推荐
相关产品推荐

