答案:EqualityComparer 提供自定义相等性比较逻辑,优先使用 IEquatable 接口,否则回退到 Object.Equals;可通过实现 IEquatable 或继承 EqualityComparer 自定义比较规则,如按特定字段比较,并确保 Equals 与 GetHashCode 一致性以避免集合异常。

EqualityComparer 是 .NET 中用于比较两个对象是否相等的一个抽象类,它定义了判断“相等”的标准。默认情况下,引用类型通过引用地址判断是否相等,值类型则逐字段比较。但在很多场景下,比如集合操作(如 Dictionary、HashSet、LINQ 的 Distinct、GroupBy 等),我们需要自定义“相等”的逻辑,这时就可以使用或实现 EqualityComparer。
默认的 EqualityComparer
System.Collections.Generic.EqualityComparer- 如果 T 实现了 IEquatable
接口,则使用该接口的 Equals 方法。 - 否则回退到 Object.Equals 方法。
例如:
public class Person : IEquatable{ public string Name { get; set; } public int Age { get; set; } public bool Equals(Person other) { if (other is null) return false; return Name == other.Name && Age == other.Age; } public override bool Equals(object obj) => Equals(obj as Person); public override int GetHashCode() => HashCode.Combine(Name, Age);}
这样在 HashSet
或 Distinct() 中就会按 Name 和 Age 判断是否重复。 自定义 EqualityComparer 类
如果你不能修改原始类(比如第三方类型),或者想在不同场景下使用不同的比较逻辑,可以继承 EqualityComparer
创建专用比较器。 例如,只按姓名比较 Person:
public class PersonNameComparer : EqualityComparer{ public override bool Equals(Person x, Person y) { if (x is null && y is null) return true; if (x is null || y is null) return false; return x.Name == y.Name; } public override int GetHashCode(Person obj) { if (obj is null) return 0; return obj.Name?.GetHashCode() ?? 0; }}
使用方式:
var people = new List{ /* ... */ }; var distinctPeople = people.Distinct(new PersonNameComparer()); 使用静态方法创建轻量比较器
.NET Core 2.1+ 提供了一个便捷方法:EqualityComparer
.Create (实际没有这个 API,但可通过封装委托实现类似效果)。虽然框架未内置基于委托的构造函数,但你可以写一个辅助类来简化。例如,创建一个通用的委托比较器:
public class DelegateComparer: EqualityComparer { private readonly Func _equals; private readonly Func _getHashCode; public DelegateComparer(Funcequals, Func getHashCode) { _equals = equals; _getHashCode = getHashCode; } public override bool Equals(T x, T y) => _equals(x, y); public override int GetHashCode(T obj) => _getHashCode(obj); }
使用示例:
var comparer = new DelegateComparer( (p1, p2) => p1?.Name == p2?.Name, p => p.Name?.GetHashCode() ?? 0 ); 关键注意事项
- Equals 和 GetHashCode 必须一致:如果两个对象 Equals 返回 true,它们的 GetHashCode 必须返回相同值。
- GetHashCode 不应抛出异常,且在对象生命周期内对于参与比较的字段应保持稳定。
- 避免在 GetHashCode 中使用可变字段,否则可能导致 HashSet 或 Dictionary 出现不可查找的问题。
基本上就这些。通过实现 IEquatable
或继承 EqualityComparer ,你可以灵活控制对象的相等性判断逻辑,适应各种数据处理需求。










