Реализация 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());
Эта перегрузка различных элементов A
s переопределяет Equals
и GetHashCode
и использует AComparerInsensitive
для выполнения сравнения.
person
Jodrell
schedule
08.04.2014