.NET中LINQ未正确过滤空属性值引发空引用异常求助
问题分析与解决方案
你踩了一个典型的反射+LINQ误区——你的过滤条件完全找错了方向!
你写的Where(Property => Property != null)是在检查PropertyInfo对象本身是否为null,但GetType().GetProperties()返回的所有属性元数据对象都是有效的,绝不会是null,所以这个过滤等于白写,完全起不到过滤「属性值为空」的作用。这就是为啥Gender属性明明没赋值(值为null)却还是被遍历到,最后调用.ToString()时触发了NullReferenceException。
核心问题拆解
你混淆了两个关键概念:
PropertyInfo:描述类属性的元数据对象,只要是从合法类型反射获取的,它本身永远不会是null- 属性值:该属性在
TestObj实例上的具体值,比如Gender的null、FirstName的"First"
你真正要过滤的是属性值为空的情况,而非属性对象本身。
修复方案
1. 修正LINQ过滤条件
把过滤逻辑改成检查属性值是否不为null,修改后的完整方法代码如下:
public static void CheckAutoPatientLookupProperties(AutoPatientLookup TestObj) { foreach (var property in TestObj.GetType().GetProperties() // 过滤掉属性值为null的项 .Where(prop => prop.GetValue(TestObj, null) != null)) { var value = property.GetValue(TestObj, null); Console.WriteLine("AutoPatientLookup Instance Property {0} = {1}", property.Name, value.ToString()); } Console.ReadKey(); }
2. 额外处理值类型默认值(可选)
你的AutoPatientLookup里有int类型的属性(PatientNumber、SSN),这些值类型的默认值是0而非null。如果想把这些默认值也当成“空值”过滤掉,可以扩展过滤逻辑:
public static void CheckAutoPatientLookupProperties(AutoPatientLookup TestObj) { foreach (var property in TestObj.GetType().GetProperties() .Where(prop => { var value = prop.GetValue(TestObj, null); // 先过滤引用类型的null if (value == null) return false; // 再过滤值类型的默认值(比如int的0) if (prop.PropertyType.IsValueType) { return !Equals(value, Activator.CreateInstance(prop.PropertyType)); } return true; })) { var value = property.GetValue(TestObj, null); Console.WriteLine("AutoPatientLookup Instance Property {0} = {1}", property.Name, value.ToString()); } Console.ReadKey(); }
3. 安全的ToString调用(防御性编程)
如果不想完全过滤空值,只是想避免空引用异常,可以用空条件运算符?.和空合并运算符??做安全处理:
Console.WriteLine("AutoPatientLookup Instance Property {0} = {1}", property.Name, property.GetValue(TestObj, null)?.ToString() ?? "[null]");
这样即使属性值为null,也只会输出[null]而不会抛出异常。
内容的提问来源于stack exchange,提问作者W.Harr
相关产品推荐
相关产品推荐

