如何用一行C#代码安全获取非空值?解决空引用异常
解决C#带完整空检查的单行取值问题
原代码的问题分析
你的代码存在两个关键问题导致空引用异常:
- 未检查
assessment本身是否为null,直接访问assessment.table1会触发空引用; FirstOrDefault(...)返回null时调用ToString(),再次引发空引用,且该调用完全多余(返回值本身就是string类型)。
修正后的单行代码(C#6+)
利用**空条件运算符(?.)和空合并运算符(??)**实现完整空检查,一行搞定:
string output = new[] { assessment?.table1?.Name ?? "", assessment?.table2?.Name ?? "", assessment?.table3?.Name ?? "" }.FirstOrDefault(s => !string.IsNullOrEmpty(s));
assessment?.table1:先判断assessment是否为null,是则返回null,否则访问table1;?.Name:判断table1是否为null,是则返回null,否则取Name属性;?? "":将null转换为空字符串,确保数组元素无null;FirstOrDefault(s => !string.IsNullOrEmpty(s)):取第一个非空、非空白的字符串,若全部为空则返回null。
其他实现方案
方案1:兼容旧版C#(无?.语法)
如果使用C#6以下版本,用三元运算符嵌套实现:
string output = assessment == null ? null : (!string.IsNullOrEmpty(assessment.table1 != null ? assessment.table1.Name : null) ? assessment.table1.Name : (!string.IsNullOrEmpty(assessment.table2 != null ? assessment.table2.Name : null) ? assessment.table2.Name : assessment.table3 != null ? assessment.table3.Name : null));
方案2:延迟执行的LINQ方案(适合扩展更多表的场景)
通过委托延迟获取值,避免不必要的属性访问,同时简化空检查:
string output = new Func<string>[] { () => assessment?.table1?.Name, () => assessment?.table2?.Name, () => assessment?.table3?.Name } .Select(func => func()) .Where(s => !string.IsNullOrEmpty(s)) .FirstOrDefault();
这个方案的优势是:只有当前面的委托返回空时,才会执行后面的委托,性能更优,且新增表只需在数组里加一行委托即可。
内容的提问来源于stack exchange,提问作者VPP
相关产品推荐
相关产品推荐

