实现IEqualityComparer<T> 不是override 的基本实现GetHashCode 和Equals。
实现IEqualityComparer<T> 允许您提供实现者的实例作为T 的相等比较器。这是几个 linq 扩展和通用集合构造函数的通用参数。
覆盖Equals 和GetHashCode 会影响对类实例进行相等性测试的方式。利用调用 Equals 和 GetHashCode 的其他实现,例如基本 = 和 != 运算符和 linq 扩展和通用集合构造函数,您不提供替代 IEqualityComparer<T>。
这些概念相似,但用途不同,不能部分互换。
让我用一个例子来扩展,
public class A
{
public string Value1 { get; set; }
public int Value2 { get; set; }
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = (hash * 23) +
StringComparer.Ordinal.GetHashCode(this.Value1);
hash = (hash * 23) + this.Value2;
return hash;
}
}
public override bool Equals(object obj)
{
var a = obj as A;
if (a == null)
{
return false;
}
if (a.Value2 != this.Value2)
{
return false;
}
return StringComparer.Ordinal.Equals(
a.Value1,
this.Value1);
}
}
A的这个实现正确地覆盖了Equals和GetHashCode,这个改变足以保证在调用linq扩展之后
var distinct = aSequneceOfA.Distinct();
distinct 不会包含具有相同Value2 和通常可比较Value1 的任何实例。无需其他接口实现即可实现此目的。
现在,假设在某些情况下我对Value1 的这个序数比较不满意,也许我需要不区分大小写。我可能会实现一个新的相等比较器。
public class AComparerInsensitive : IEqualityComparer<A>
{
public bool Equals(A x, A y)
{
if (x == null)
{
return y == null;
}
if (y == null)
{
return false;
}
if (x.Value2 != y.Value2)
{
return false;
}
return StringComparer.CurrentCultureIgnoreCase.Equals(
x.Value1,
y.Value1)
}
public int GetHashCode(A a)
{
if (a == null)
{
return 0;
}
unchecked
{
int hash = 17;
hash = (hash * 23) +
StringComparer.CurrentCultureIgnoreCase.GetHashCode(
a.Value1);
hash = (hash * 23) + a.Value2;
return hash;
}
}
}
这将允许我调用 Distinct 的替代重载,
var insensitivelyDistinct = aSequneceOfA.Distinct(
new AComparerInsensitive());
这种重载的不同忽略 As 被覆盖 Equals 和 GetHashCode 并使用 AComparerInsensitive 执行比较。