如何比较未知类型对象的类型与属性值是否完全一致?
实现对象属性值的深度比较方法
需求说明
需要编写一个通用方法,比较两个未知类型的对象:
- 当二者类型完全相同且所有公共属性值一致时返回
True - 否则返回
False - 不重写对象的
Equals方法,保留原有==运算符的默认行为 - 用于从对象集合中匹配属性值一致的元素,对象不一定是同一类型或实例
实现代码
以下是包含递归处理、循环引用防护的完整实现:
using System; using System.Collections; using System.Collections.Generic; using System.Reflection; public static class ObjectComparer { public static bool CheckEqual(object a, object b) { // 处理null情况:都为null返回true,一个为null返回false if (ReferenceEquals(a, b)) return true; if (a == null || b == null) return false; // 类型不同直接返回false if (a.GetType() != b.GetType()) return false; // 处理值类型和字符串(值类型直接用==比较,字符串特殊处理) if (a is ValueType || a is string) return a.Equals(b); // 处理集合类型 if (a is IEnumerable enumerableA && b is IEnumerable enumerableB) { var enumeratorA = enumerableA.GetEnumerator(); var enumeratorB = enumerableB.GetEnumerator(); bool hasNextA, hasNextB; while ((hasNextA = enumeratorA.MoveNext()) && (hasNextB = enumeratorB.MoveNext())) { if (!CheckEqual(enumeratorA.Current, enumeratorB.Current)) return false; } // 两个集合元素数量必须一致 return hasNextA == hasNextB; } // 用哈希集合跟踪已比较的对象,防止循环引用导致无限递归 var comparedObjects = new HashSet<Tuple<object, object>>(); return DeepCompareProperties(a, b, comparedObjects); } private static bool DeepCompareProperties(object a, object b, HashSet<Tuple<object, object>> comparedObjects) { var tuple = Tuple.Create(a, b); if (comparedObjects.Contains(tuple)) return true; // 已比较过,视为相等(避免循环引用死循环) comparedObjects.Add(tuple); // 获取所有公共实例属性 var properties = a.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { // 跳过索引器属性 if (prop.GetIndexParameters().Length > 0) continue; var valueA = prop.GetValue(a); var valueB = prop.GetValue(b); // 递归比较属性值 if (!CheckEqual(valueA, valueB)) return false; } return true; } } // 测试用类 public class ExampleClass { public string PropertyA { get; set; } public string PropertyB { get; set; } public List<int> NestedList { get; set; } } // 调用示例 public class Program { public static void Main() { var a = new ExampleClass() { PropertyA = "A", PropertyB = "B", NestedList = new List<int> { 1, 2, 3 } }; var b = new ExampleClass() { PropertyA = "A", PropertyB = "B", NestedList = new List<int> { 1, 2, 3 } }; var c = new ExampleClass() { PropertyA = "C", PropertyB = "B", NestedList = new List<int> { 1, 2 } }; Console.WriteLine(ObjectComparer.CheckEqual(a, b)); // 输出 True Console.WriteLine(ObjectComparer.CheckEqual(a, c)); // 输出 False } }
关键细节说明
- null处理:先判断引用相等,再处理单null的情况
- 类型校验:严格要求两个对象类型完全相同(子类和父类会被视为不同)
- 值类型与字符串:直接使用
Equals比较,避免反射开销 - 集合支持:遍历集合元素逐个比较,确保元素数量和内容都一致
- 循环引用防护:用
HashSet记录已比较的对象对,防止无限递归 - 索引器跳过:忽略带有索引参数的属性,避免不必要的复杂处理
内容的提问来源于stack exchange,提问作者ceds
相关产品推荐
相关产品推荐

