Quelle est la différence entre IEqualityComparer<T>, et IEquatable<T>?
Je veux comprendre les scénarios où IEqualityComparer<T>
et IEquatable<T>
doit être utilisé.
La documentation MSDN pour les deux l'air très similaires.
- MSDN sez:"Cette interface permet la mise en œuvre de l'égalité de comparaison pour les collections." qui, bien sûr, est déduit de la réponse choisie. MSDN recommande également hériter de
EqualityComparer<T>
au lieu de la mise en œuvre de l'interface "parce queEqualityComparer<T>
tests d'égalité à l'aide deIEquatable<T>
- ... ci-dessus suggère que je devrais créer une collection personnalisée pour toute
T
la mise en œuvre deIEquatable<T>
. Serait une collection commeList<T>
avoir une sorte de bug subtil de il autrement? - bonne explication anotherchris.net/csharp/...
Vous devez vous connecter pour publier un commentaire.
IEqualityComparer<T>
est une interface pour un objet qui effectue la comparaison de deux objets de typeT
.IEquatable<T>
est pour un objet de typeT
de sorte qu'il peut se comparer à l'autre.Avant de décider d'utiliser
IEquatable<T>
ouIEqualityComparer<T>
,on pourrait se demander:
Si il n'y a qu'une seule façon de tester les deux instances de
T
pour l'égalité, ou si l'une de plusieurs méthodes est préférée,IEquatable<T>
serait le bon choix: Cette interface est censé être mis en œuvre que parT
lui-même, de sorte qu'une instance deT
a la connaissance interne de façon à se comparer à une autre instance deT
.D'autre part, s'il y a plusieurs également des méthodes de comparaison de deux
T
s pour l'égalité,IEqualityComparer<T>
semblerait plus approprié: Cette interface n'est pas destiné à être mis en œuvre parT
lui-même, mais par d'autres "externe" des classes. Par conséquent, lors de l'essai de deux instances deT
pour l'égalité, parce queT
n'a pas de connaissance interne de l'égalité, vous aurez à faire un choix explicite d'uneIEqualityComparer<T>
instance qui effectue le test en fonction de vos exigences spécifiques.Exemple:
Nous allons tenir compte de ces deux types (qui sont censés avoir la valeur sémantique):
Pourquoi un seul de ces types héritent
IEquatable<>
, mais pas dans l'autre?En théorie, il y a une seule façon logique de la comparaison de deux instances de chaque type: Ils sont égaux si la
X
etY
propriétés dans les deux cas, sont égaux. Selon cette pensée, les deux types doivent mettre en œuvreIEquatable<>
, car il ne semble pas probable qu'il existe d'autres moyens efficaces de faire un test d'égalité.Le problème ici est que la comparaison de nombres à virgule flottante pour l'égalité peut ne pas fonctionner comme prévu, en raison de minutes erreurs d'arrondi. Il existe différentes méthodes de comparaison de nombres à virgule flottante pour la quasi-égalité, chacune avec ses avantages et inconvénients, et vous pourriez être en mesure de choisir vous-même la méthode qui convient.
Notez que la page je lien (ci-dessus) indique explicitement que ce test pour la quasi-égalité a quelques faiblesses. Puisque c'est un
IEqualityComparer<T>
mise en œuvre, vous pouvez simplement remplacez-la si elle n'est pas assez bon pour vos besoins.IEqualityComparer<T>
de mise en œuvre de doit mettre en œuvre une relation d'équivalence, ce qui implique que, dans tous cas où les deux objets à comparer égale à un tiers, ils doit comparer égale les unes des autres. Toute classe qui implémenteIEquatable<T>
ouIEqualityComparer<T>
de manière contraire à la ci-dessus est cassé.IEqualityComparer<String>
qui estime qu'un "bonjour" de l'égalité à la fois "Bonjour" et "bonsoir" doit envisager de "Bonjour" et "bonsoir" égale les unes des autres, mais pour la plupart des méthodes de comparaison qui ne serait pas un problème.GetHashCode
devrait vous permettre de déterminer rapidement si les deux valeurs sont différentes. Les règles sont à peu près comme suit: (1)GetHashCode
doit toujours produire le même code de hachage pour la même valeur. (2)GetHashCode
doit être rapide (plus rapide queEquals
). (3)GetHashCode
n'a pas à être précis (pas aussi précise queEquals
). Cela signifie qu'il peut produire le même code de hachage pour des valeurs différentes. Le plus précis vous pouvez le faire, le mieux, mais il est probablement plus important que rapide.Vous avez déjà eu la définition de base de ce qu'ils sont. En bref, si vous mettez en œuvre
IEquatable<T>
de la classeT
, leEquals
méthode sur un objet de typeT
vous indique si l'objet lui-même (un cours d'essai pour l'égalité) est égale à une autre instance du même typeT
. Alors que,IEqualityComparer<T>
est pour tester l'égalité de deux instances deT
, généralement en dehors de la portée des instances deT
.À ce qu'ils sont pour peut être déroutant au premier abord. À partir de la définition, il devrait être clair que, partant,
IEquatable<T>
(défini dans la classeT
lui-même) doit être la norme de facto pour représenter la singularité de ses objets/instances.HashSet<T>
,Dictionary<T, U>
(en tenant compte deGetHashCode
est remplacé en tant que bien),Contains
surList<T>
etc faire usage de cette. La mise en œuvre deIEqualityComparer<T>
surT
n'aide pas le ci-dessus mentionné les cas généraux. Par la suite, il n'y a que peu de valeur pour la mise en œuvre deIEquatable<T>
sur toute autre catégorie autre queT
. Ce:rarement du sens.
D'autre part
est comment il devrait être fait.
IEqualityComparer<T>
peut être utile lorsque vous avez besoin d'une validation personnalisée de l'égalité, mais pas comme une règle générale. Par exemple, dans une classe dePerson
à un certain point, vous aurez besoin de tester l'égalité de deux personnes sur la base de leur âge. Dans ce cas, vous pouvez le faire:De les tester, essayer
De même
IEqualityComparer<T>
surT
ne fait pas de sens.Vrai cela fonctionne, mais n'a pas l'air bon pour les yeux et va à l'encontre de la logique.
Généralement de ce que vous avez besoin est
IEquatable<T>
. Aussi, idéalement, vous ne pouvez avoir qu'unIEquatable<T>
tandis que de multiplesIEqualityComparer<T>
est possible sur la base de différents critères.La
IEqualityComparer<T>
etIEquatable<T>
sont exactement analogue àComparer<T>
etIComparable<T>
qui sont utilisés à des fins de comparaison plutôt que de les assimiler; un bon thread ici où j'ai écrit la même réponse 🙂public int GetHashCode(Person obj)
doit retournerobj.GetHashCode()
obj.Age.GetHashCode
. modifier.person.GetHashCode
n'importe où.... pourquoi voulez-vous remplacer? - Nous remplacer parce que le point deIEqualityComparer
est d'avoir une autre comparaison mise en œuvre, selon nos règles - les règles que nous connaissons vraiment bien.Age
bien, je l'appelleAge.GetHashCode
. L'âge est de typeint
, mais quel que soit le type est le code de hachage de contrat .NET est quedifferent objects can have equal hash but equal objects cant ever have different hashes
. C'est un contrat, nous pouvons croire aveuglément. Assurer à notre clientèle des comparateurs doivent respecter cette règle. Si jamais l'appel desomeObject.GetHashCode
sauts de choses, alors c'est le problème avec les réalisateurs de type desomeObject
, ce n'est pas notre problème.IEqualityComparer est à utiliser lorsque l'égalité de deux objets en usage externe, mise en œuvre, par exemple, si vous vouliez définir un comparateur pour les deux types que vous n'avez pas la source, ou pour les cas où l'égalité entre les deux choses n'a de sens que dans certains contexte.
IEquatable est pour l'objet lui-même (celui d'être comparé pour l'égalité) à mettre en œuvre.
L'on compare les deux
T
s. Les autres peuvent se comparer à d'autresT
s. Habituellement, vous aurez seulement besoin d'utiliser un à la fois, pas deux.