嵌套集合对象深度比较:如何实现MyClass列表的相等判断方法?
实现IReadOnlyList的逻辑相等判断方法
给定以下类定义:
public class MyClass { public int[] BunchOfNumbers { get; set; } public int SomeOtherNumber { get; set; } }
需要实现签名如下的相等性判断方法,要求仅当两个列表在逻辑上完全相等时返回true,需处理空值、数组null等复杂情况:
public bool AreItemsEqual(IReadOnlyList<MyClass> objA, IReadOnlyList<MyClass> objB) { ... }
简便实现方案
方案一:手动遍历比较(兼容性强,适用于所有.NET版本)
先编写辅助方法处理单个MyClass实例的相等判断,再遍历列表逐个比较:
- 单个
MyClass实例的比较方法
private static bool AreMyClassEqual(MyClass a, MyClass b) { // 引用直接相等或均为null if (ReferenceEquals(a, b)) return true; // 其中一个为null,另一个非null if (a is null || b is null) return false; // 比较值类型字段 if (a.SomeOtherNumber != b.SomeOtherNumber) return false; // 比较数组:将null转换为空数组后,用SequenceEqual判断元素是否完全一致 return Enumerable.SequenceEqual(a.BunchOfNumbers ?? Array.Empty<int>(), b.BunchOfNumbers ?? Array.Empty<int>()); }
- 列表相等判断方法
public bool AreItemsEqual(IReadOnlyList<MyClass> objA, IReadOnlyList<MyClass> objB) { // 引用直接相等或均为null if (ReferenceEquals(objA, objB)) return true; // 其中一个为null,另一个非null if (objA is null || objB is null) return false; // 元素数量不同直接返回false if (objA.Count != objB.Count) return false; // 逐个比较每个元素 for (int i = 0; i < objA.Count; i++) { if (!AreMyClassEqual(objA[i], objB[i])) { return false; } } return true; }
方案二:使用IEqualityComparer+LINQ(代码更简洁)
将MyClass的相等逻辑封装为IEqualityComparer<MyClass>实现,再借助LINQ的SequenceEqual方法完成列表比较:
- 实现自定义相等比较器
public class MyClassEqualityComparer : IEqualityComparer<MyClass> { public bool Equals(MyClass x, MyClass y) { if (ReferenceEquals(x, y)) return true; if (x is null || y is null) return false; if (x.SomeOtherNumber != y.SomeOtherNumber) return false; return Enumerable.SequenceEqual(x.BunchOfNumbers ?? Array.Empty<int>(), y.BunchOfNumbers ?? Array.Empty<int>()); } public int GetHashCode(MyClass obj) { if (obj is null) return 0; // 计算哈希码,结合值字段和数组的结构哈希 var arrayHash = obj.BunchOfNumbers?.Aggregate(0, (currentHash, num) => HashCode.Combine(currentHash, num)) ?? 0; return HashCode.Combine(obj.SomeOtherNumber, arrayHash); } }
- 简化的列表相等判断方法
public bool AreItemsEqual(IReadOnlyList<MyClass> objA, IReadOnlyList<MyClass> objB) { if (ReferenceEquals(objA, objB)) return true; if (objA is null || objB is null) return false; return objA.SequenceEqual(objB, new MyClassEqualityComparer()); }
关键注意点
- 必须处理
null场景:包括列表本身为null、列表中的MyClass实例为null、BunchOfNumbers数组为null的情况 - 数组的相等判断需要用
Enumerable.SequenceEqual,而非默认的引用比较 - 哈希码的计算要与相等逻辑保持一致,避免使用数组默认的引用哈希(仅当需要用到哈希表等场景时需关注)
内容的提问来源于stack exchange,提问作者millie
相关产品推荐
相关产品推荐

