Linq Expression搜索过滤器报空引用异常,求技术排查解决
排查Linq Expression搜索过滤器的空引用异常(Object reference not set to an instance of an object)
我帮你梳理下这段Linq Expression代码里可能触发空引用异常的核心原因,以及对应的修复方案:
可能的异常原因
- 属性值为null时调用实例方法:如果目标对象的某个string属性是
null,直接调用ToLower()会触发空引用异常——因为null没有实例方法可以调用,这是最常见的触发点。 - MethodInfo获取失败:虽然代码里尝试获取
ToLower和Contains方法,但如果反射调用返回null(比如方法签名不匹配),后续调用Expression.Call时会因为方法引用为空报错。 - 属性名与属性值数组长度不匹配:如果
propertyNames和propertyValue数组长度不一致,循环时可能会访问到数组越界的位置,间接引发空引用或索引异常。
解决办法
针对上述问题,我们需要做以下几个关键修复:
- 添加属性null检查:在调用
ToLower()和Contains()前,先判断属性值是否为null,只有非空时才执行后续逻辑。 - 确保MethodInfo有效:添加反射获取方法后的null校验,避免后续调用空方法引用。
- 校验数组长度一致性:避免因数组长度不匹配导致的索引问题。
- 预处理搜索值:提前将搜索值转小写,避免重复处理,同时处理搜索值为
null的情况。
修正后的完整代码
public static Expression<Func<T, bool>> SearchExpression<T>(string[] propertyNames, string[] propertyValues) { var parameterExp = Expression.Parameter(typeof(T), "type"); MethodInfo toLowerMethod = typeof(string).GetMethod("ToLower", Type.EmptyTypes); MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) }); // 校验反射获取的方法是否有效 if (toLowerMethod == null || containsMethod == null) throw new InvalidOperationException("无法获取字符串的ToLower或Contains方法"); // 校验属性名和属性值数组长度一致 if (propertyNames.Length != propertyValues.Length) throw new ArgumentException("属性名数组与属性值数组长度必须匹配"); Expression finalExpression = Expression.Constant(true); for (int i = 0; i < propertyNames.Length; i++) { string propertyName = propertyNames[i]; // 预处理搜索值:转小写,空值直接跳过该条件 string searchValue = propertyValues[i]?.ToLower(); if (string.IsNullOrEmpty(searchValue)) continue; // 获取目标属性的表达式 MemberExpression propertyExp = Expression.Property(parameterExp, propertyName); // 构建属性非空的检查表达式 Expression isPropertyNotNull = Expression.NotEqual(propertyExp, Expression.Constant(null)); // 构建属性值转小写的表达式(仅当属性非空时执行) Expression propertyToLower = Expression.Call(propertyExp, toLowerMethod); // 构建Contains调用表达式 Expression containsCall = Expression.Call(propertyToLower, containsMethod, Expression.Constant(searchValue)); // 合并非空检查与Contains条件:属性非空 && 属性值包含搜索值 Expression propertyCondition = Expression.AndAlso(isPropertyNotNull, containsCall); // 将当前条件合并到最终表达式中 finalExpression = Expression.AndAlso(finalExpression, propertyCondition); } return Expression.Lambda<Func<T, bool>>(finalExpression, parameterExp); }
关键修复点说明
- 对搜索值做了
null处理,空值直接跳过对应条件,避免无效判断; - 给每个属性添加了非空检查,用
Expression.AndAlso确保只有属性非空时才调用ToLower()和Contains(); - 增加了MethodInfo和数组长度的校验,提前抛出明确的异常,避免后续隐性错误;
- 提前将搜索值转小写,减少表达式中的重复操作,提升效率。
内容的提问来源于stack exchange,提问作者Samir Mistry
相关产品推荐
相关产品推荐

