C#求两个不同自定义列表交集失败,Equals方法未触发求助
问题原因及修复方案
你的代码存在几个核心问题,导致Intersect返回空集合且Equals方法从未触发:
1. 未重写GetHashCode方法
LINQ的Intersect内部依赖哈希表实现,会优先比较对象的哈希码。如果两个对象哈希码不同,根本不会调用Equals方法。你仅实现了IEquatable<CompareObject>的Equals,但未重写GetHashCode,默认哈希码基于对象引用生成,即使compareString相同,不同对象的哈希码也不一致,导致无法匹配交集。
2. 子类构造函数未复用父类逻辑
CompareObjectA和CompareObjectB的构造函数直接赋值字段,未调用父类构造函数,既不符合面向对象设计原则,也容易因重复代码引入错误。
3. Equals方法未处理null及类型差异
当前Equals方法若other为null,直接访问other.compareString会抛出空引用异常,同时未处理子类类型不同的情况(虽然你已将对象转为CompareObject,但规范上需做校验)。
修复后的完整代码
internal class CompareObject : IEquatable<CompareObject> { public CompareObject(object myParentObject, string compareString) { this.myParentObject = myParentObject; this.compareString = compareString; } public string compareString { get; set; } public object myParentObject { get; set; } public bool Equals(CompareObject? other) { if (other is null) return false; // 确保类型一致(若允许子类跨类型比较可移除此判断) if (GetType() != other.GetType()) return false; return string.Equals(this.compareString, other.compareString, StringComparison.Ordinal); } // 重写Object.Equals保证逻辑一致性 public override bool Equals(object? obj) { return Equals(obj as CompareObject); } // 基于比较字段生成哈希码 public override int GetHashCode() { return compareString?.GetHashCode(StringComparison.Ordinal) ?? 0; } } internal class CompareObjectA : CompareObject { public CompareObjectA(customClassA myParentObject) : base(myParentObject, myParentObject.customCompareField) { } } internal class CompareObjectB : CompareObject { public CompareObjectB(customClassB myParentObject) : base(myParentObject, myParentObject.customCompareField) { } } public void Execute() { var listA = new List<CompareObjectA>(<<SAMPLE VALUES>>); var listB = new List<CompareObjectB>(<<SAMPLE VALUES>>); // 用Cast更简洁地转换类型 var listC = listA.Cast<CompareObject>().Intersect(listB.Cast<CompareObject>()).ToList(); }
额外说明
- 使用
string.Equals并指定StringComparison,可避免文化差异导致的比较错误,可根据需求选择OrdinalIgnoreCase(忽略大小写)等枚举值。 - 重写
Object.Equals是为了保证通过object类型比较时逻辑一致,避免出现矛盾结果。
内容的提问来源于stack exchange,提问作者Christoffel de Gruyter
相关产品推荐
相关产品推荐

