C#使用Func表达式调用OrderBy排序时空引用异常问题
问题原因
- 空值判断逻辑完全写反:你使用了逻辑与
&&拼接判断条件,仅当Recipient和Address同时为null时才会返回空值。只要Recipient不为null、哪怕Address是null,判断结果都会为false,直接进入后续的属性访问逻辑,触发空引用。这也是你把返回值从null换成string.Empty依然报错的核心原因——空对象的属性访问根本没走到你写的返回默认值的分支。 - 选择
dynamic作为排序键返回类型会引入额外异常:当排序字段是值类型(比如数字类型的Nummer)时,编译器会自动生成装箱逻辑,而三元表达式返回的null是无类型引用类型,两者类型不匹配,在EF Core等非内存LINQ提供程序下会直接抛出执行异常。 - 你漏了对最上层
Inhalt属性的空判断,该属性为null时同样会触发空引用。
修复方案
把表达式列表的泛型参数从dynamic改成object(排序仅要求键实现IComparable接口,object完全兼容,不会引入dynamic的绑定开销和类型问题),直接使用C#内置的空条件运算符?.即可生成正确的逐层短路空判断逻辑,不需要手动写三元判断:
List<Expression<Func<Data, object>>> orderingExpression = new List<Expression<Func<Data, object>>>(); // 空条件运算符会自动逐层判断空,任意节点为null就直接返回null,不会访问下级属性 orderingExpression.Add(x => x.Inhalt?.Recipient?.Address?.Nummer); orderingExpression.Add(x => x.Inhalt?.Recipient?.Address?.Street); // 原有排序调用逻辑无需修改 datatemp = datatemp.OrderBy(orderingExpression.First()).ThenBy(orderingExpression.Last());
如果你使用的LINQ提供程序版本过老不支持空条件运算符,手动写判断时注意使用逻辑或||实现短路逻辑,同时将属性值统一转成object保证三元表达式两个分支类型一致:
orderingExpression.Add(x => x.Inhalt == null || x.Inhalt.Recipient == null || x.Inhalt.Recipient.Address == null ? null : (object)x.Inhalt.Recipient.Address.Nummer ); orderingExpression.Add(x => x.Inhalt == null || x.Inhalt.Recipient == null || x.Inhalt.Recipient.Address == null ? null : (object)x.Inhalt.Recipient.Address.Street );
注意:逻辑或
||是短路运算符,只要前面的条件成立(比如判断到Inhalt为null),就不会执行后面的属性访问逻辑,从根源上避免空引用。
内容的提问来源于stack exchange,提问作者luprok
相关产品推荐
相关产品推荐

