如何区分C#子类中继承属性与自身定义的属性?
这问题我之前踩过坑!你用Except没效果的核心原因是:PropertyInfo实例的引用相等性不等于属性的逻辑相等性。子类继承来的属性对应的PropertyInfo对象,和父类中定义该属性的PropertyInfo对象不是同一个实例,所以Except默认的引用比较会把它们当成不同的元素,自然没法过滤掉继承属性。
最简单的解决方案:用DeclaringType过滤
直接通过PropertyInfo.DeclaringType属性判断,这个属性会返回定义该属性的原始类。子类自身定义的属性,DeclaringType就是typeof(Child);继承来的属性则是父类的类型(这里是typeof(Father))。
代码示例:
var childOwnProperties = typeof(Child).GetProperties() .Where(p => p.DeclaringType == typeof(Child));
运行这段代码,只会返回Child类自己定义的Name属性,完美过滤掉从Father继承来的Id和Price。
为什么你的原代码不行?
当你调用typeof(Child).GetProperties()时,返回的继承属性(比如Id)的PropertyInfo实例,虽然它代表的是父类定义的属性,但这个实例和typeof(Father).GetProperties()返回的Id属性实例是不同的对象。Except默认用Object.Equals做引用比较,所以会认为这两个是不同的元素,不会排除它们。
进阶:自定义相等比较器用Except
如果你一定要用Except方法,可以自定义一个IEqualityComparer<PropertyInfo>,根据属性的逻辑标识来判断相等性(比如属性名称+属性类型,或者更严谨的元数据标识):
public class PropertyInfoEqualityComparer : IEqualityComparer<PropertyInfo> { public bool Equals(PropertyInfo x, PropertyInfo y) { if (x == null || y == null) return x == y; // 比较属性的名称和类型,确保逻辑上是同一个属性 return x.Name == y.Name && x.PropertyType == y.PropertyType; } public int GetHashCode(PropertyInfo obj) { return obj.Name.GetHashCode() ^ obj.PropertyType.GetHashCode(); } }
然后这样使用:
var childProperties = typeof(Child).GetProperties() .Except(typeof(Father).GetProperties(), new PropertyInfoEqualityComparer());
不过这种方法不如直接用DeclaringType过滤简洁直观,除非你有特殊场景需要用Except。
内容的提问来源于stack exchange,提问作者Yahya Hussein

