Hai già ottenuto la definizione di base di ciò che sono . In breve, se si implementa IEquatable<T>
in classe T
, il Equals
metodo su un oggetto di tipo T
indica se l'oggetto stesso (quello che viene testato per l'uguaglianza) è uguale a un'altra istanza dello stesso tipo T
. Considerando che, IEqualityComparer<T>
è per testare l'uguaglianza di due casi qualsiasi T
, in genere al di fuori dell'ambito dei casi di T
.
Quanto a cosa servono possono essere fonte di confusione all'inizio. Dalla definizione dovrebbe essere chiaro che quindi IEquatable<T>
(definito nella classe T
stessa) dovrebbe essere lo standard di fatto per rappresentare l'unicità dei suoi oggetti / istanze. HashSet<T>
, Dictionary<T, U>
(Considerando GetHashCode
viene sovrascritto pure), Contains
il List<T>
etc fanno uso di questo. L'implementazione IEqualityComparer<T>
su T
non aiuta i casi generali sopra menzionati. Successivamente, c'è poco valore per l'implementazione IEquatable<T>
su qualsiasi altra classe diversa da T
. Questo:
class MyClass : IEquatable<T>
raramente ha senso.
D'altro canto
class T : IEquatable<T>
{
//override ==, !=, GetHashCode and non generic Equals as well
public bool Equals(T other)
{
//....
}
}
è come dovrebbe essere fatto.
IEqualityComparer<T>
può essere utile quando si richiede una convalida personalizzata dell'uguaglianza, ma non come regola generale. Ad esempio, in una classe Person
ad un certo punto potrebbe essere necessario testare l'uguaglianza di due persone in base alla loro età. In tal caso puoi fare:
class Person
{
public int Age;
}
class AgeEqualityTester : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return x.Age == y.Age;
}
public int GetHashCode(Person obj)
{
return obj.Age.GetHashCode;
}
}
Per provarli, prova
var people = new Person[] { new Person { age = 23 } };
Person p = new Person() { age = 23 };
print people.Contains(p); //false;
print people.Contains(p, new AgeEqualityTester()); //true
Allo stesso modo IEqualityComparer<T>
il T
non ha senso.
class Person : IEqualityComparer<Person>
È vero che funziona, ma non ha un bell'aspetto per gli occhi e sconfigge la logica.
Di solito quello che ti serve è IEquatable<T>
. Inoltre, idealmente, puoi averne solo uno IEquatable<T>
mentre IEqualityComparer<T>
sono possibili multipli in base a criteri diversi.
I IEqualityComparer<T>
e IEquatable<T>
sono esattamente analoghi a Comparer<T>
e IComparable<T>
che sono usati a fini di confronto piuttosto che equivalenti; un buon thread qui dove ho scritto la stessa risposta :)
EqualityComparer<T>
invece di implementare l'interfaccia "perchéEqualityComparer<T>
verifica l'uguaglianza usandoIEquatable<T>