C#中检查可能为null的引用的正确方法是什么?
警告产生原因
你写的boardMap[i,j]是二维数组的索引器访问,编译器无法保证前后两次访问boardMap[i,j]返回的是同一个值(比如多线程场景下你判断完非null之后,其他线程刚好把这个位置的值改成了null),所以哪怕你加了非null判断,编译器还是会认为后续访问的boardMap[i,j]有null的可能,因此触发警告。
推荐的修复方案
方案1:将索引访问结果提前存入局部变量(最稳妥,适合新手)
先把boardMap[i,j]的取值存到一个局部变量里,后续判断和读取都用这个局部变量,编译器就能确定非null分支里的变量不可能为null,警告会自动消失:
// 先把值取出来存到局部变量 var currentCell = boardMap[i,j]; if (currentCell != null) { Console.Write(currentCell.color.ToString() + " " + currentCell.type.ToString()); } else { Console.Write("X"); }
方案2:使用属性模式匹配简化写法
C# 8.0及以上版本可以用is {}的属性模式,判断非null的同时直接把值赋值给局部变量,代码更简洁:
if (boardMap[i,j] is {} currentCell) { Console.Write(currentCell.color.ToString() + " " + currentCell.type.ToString()); } else { Console.Write("X"); }
方案3:用三目运算符进一步简化
如果逻辑比较简单,也可以合并成一行写法:
var currentCell = boardMap[i,j]; Console.Write(currentCell != null ? $"{currentCell.color} {currentCell.type}" : "X");
注:上面的$""是C#的字符串插值语法,比字符串拼接的写法更易读
这类null检查的注意点
- 不要反复对同一个索引/属性进行多次取值,优先存到局部变量后再操作,除了消除警告之外,还能避免两次取值结果不一致导致的逻辑bug。
- 不推荐新手用
!(null包容运算符)强制抑制警告,比如boardMap[i,j]!.color的写法,除非你完全确定这个位置的值不可能为null,否则很容易引发运行时空引用异常。
内容的提问来源于stack exchange,提问作者Ewa Wójcik
相关产品推荐
相关产品推荐

