Est-il complet IEquatable mise en œuvre de référence?
Beaucoup de mes questions ici, sur tant de préoccupations IEquatable mise en œuvre. Je l'ai trouvé extrêmement difficile à mettre en œuvre correctement, parce qu'il y a de nombreux bugs cachés dans la naïveté de la mise en œuvre, et les articles que j'ai trouvé à ce sujet sont tout à fait incomplète. Je veux trouver ou écrire une référence définitive qui doit inclure:
- Comment mettre en œuvre IEquatable correctement
- Comment remplacer Égale correctement
- Comment remplacer GetHashCode correctement
- Comment mettre en œuvre la méthode ToString correctement
- Comment mettre en œuvre l'opérateur == correctement
- Comment mettre en œuvre l'opérateur != correctement
Une telle référence complet qui existe déjà?
PS: Même Référence MSDN semble imparfait pour moi
Vous devez vous connecter pour publier un commentaire.
La mise en œuvre de
IEquatable<T>
pour un Type de ValeurLa mise en œuvre de
IEquatable<T>
pour un type de valeur est un peu différente de celle d'un type de référence. Supposons que nous avons le mettre en Œuvre-Vos-Propres-Valeur de Type archétype, un nombre Complexe struct.Notre première étape serait de mettre en place
IEquatable<T>
et remplacerObject.Equals
etObject.GetHashCode
:Avec très peu d'effort, nous avons une mise en œuvre correcte, à l'exception des opérateurs. En ajoutant les opérateurs est également une mince affaire:
Un lecteur attentif pour remarquer que nous devrions probablement mettre en œuvre
IEquatable<double>
depuisComplex
numéros pourraient être interchangeables avec la valeur sous-jacente de type.Nous avons besoin de quatre opérateurs si l'on ajoute
IEquatable<double>
, parce que vous pouvez avoirComplex == double
oudouble == Complex
(et de même pouroperator !=
):Donc là vous l'avez, avec un minimum d'effort, nous avons une juste et utile de la mise en œuvre
IEquatable<T>
pour un type de valeur:is
paramètre, qui sera de retourfalse
siother
est soitnull
ou d'un type différent. J'ai mis à jour votre post, n'hésitez pas à la restauration ou un commentaire si vous êtes en désaccord.Equals(Object)
qui serait la cause d'uneComplex
rapport à lui-même égal à undouble
est illégitime, parce qu'une telle comparaison ne serait pas de nature réflexive; je dirais que sidouble
s'élargit àComplex
, unEquals(double)
surcharge doit exister mais qui ont un[Obsolete]
tag, pour éviter un Complexe, d'une double comparaison de donner des résultats incohérents avec un double-Complexe de la comparaison. Pour être sûr, il y a assez de mauvais spots dans le cadre (par exemple,(1.0).Equals(1.0f)
convertit1.0f
àdouble
et les rendements vrai;(1.0f).Equals(1.0)
convertit1.0
àobject
et renvoie false)Equals
de manière à violer l'attente de transitivité, je suis en désaccord avec cette recommandation, et espère que l'auteur revienne, mais je suis réticent à modifier conseiller qui a été délibérément donné.Je crois à obtenir quelque chose d'aussi simple que la vérification des objets pour l'égalité correcte est un peu délicat avec .NET design.
Pour Struct
1) mettre en Œuvre
IEquatable<T>
. Il améliore les performances sensiblement.2) Puisque vous allez avoir votre propre
Equals
maintenant, remplacerGetHashCode
, et être compatible avec les différents égalité vérification de remplacerobject.Equals
ainsi.3) Surcharge
==
et!=
les opérateurs n'ont pas besoin d'être religieusement fait depuis le compilateur avertira si vous involontairement assimiler une structure à l'autre avec une==
ou!=
, mais son bon de le faire pour être cohérent avecEquals
méthodes.Pour La Classe
À partir de MS:
Pour moi
==
se sent comme la valeur de l'égalité, de plus en plus comme un sucre syntaxique pourEquals
méthode. Écrita == b
est beaucoup plus intuitif que d'écrirea.Equals(b)
. Rarement nous aurons besoin de vérifier la référence de l'égalité. En résumé les niveaux traiter avec la logique des représentations d'objets physiques, ce n'est pas quelque chose que nous devons vérifier. Je pense avoir différentes sémantiques pour==
etEquals
peut effectivement être source de confusion. Je crois qu'il doit avoir été==
pour la valeur de l'égalité et deEquals
de référence (ou un nom commeIsSameAs
) l'égalité à la première place. J'aimerais pas prendre MS directive au sérieux ici, et pas seulement parce qu'il n'est pas naturel pour moi, mais aussi parce que la surcharge==
ne fait pas de mal majeure. C'est à la différence de pas primordial non génériqueEquals
ouGetHashCode
qui peut mordre en retour, parce que le cadre n'utilise pas==
n'importe où, mais seulement si nous avons nous-même de l'utiliser. Le seul réel avantage, je le gain de ne pas surcharger==
et!=
sera la cohérence avec la conception de l'ensemble du cadre sur lequel je n'ai aucun contrôle. Et c'est en effet une grande chose, donc, malheureusement je m'en tiendrai à ce.Avec référence sémantique (mutable objets)
1) Remplacer
Equals
etGetHashCode
.2) la mise en Œuvre de
IEquatable<T>
n'est pas un must, mais serait sympa si vous en avez un.Avec la valeur sémantique (des objets immuables)
C'est la partie la plus délicate. Peut obtenir facilement foiré si pas pris en charge..
1) Remplacer
Equals
etGetHashCode
.2) Surcharge
==
et!=
pour correspondre àEquals
. Assurez-vous qu'il fonctionne pour les valeurs null.2) la mise en Œuvre de
IEquatable<T>
n'est pas un must, mais serait sympa si vous en avez un.Prendre soin de voir comment elle devait s'en sortent si votre classe peut être hérité, dans de tels cas, vous aurez à déterminer si un objet de classe de base peut être égal à un objet de classe dérivée. Idéalement, si aucun objet de la classe dérivée est utilisée pour l'égalité de la vérification, puis une classe de base peut être égale à une classe dérivée de l'instance et, dans ce cas, il n'est pas nécessaire de vérifier
Type
l'égalité dans le génériqueEquals
de la classe de base.En général, prendre soin de ne pas dupliquer le code. J'aurais pu faire un générique classe de base abstraite (
IEqualizable<T>
ou presque) comme un modèle pour permettre la ré-utilisation plus facile, mais malheureusement, en C# qui ne m'empêche de dériver de classes supplémentaires.À la lecture de MSDN, je suis assez certain que le meilleur exemple d'une bonne mise en œuvre est dans le IEquatable.Méthode Equals page. Mon seul écart est la suivante:
Pour ceux qui s'interrogent sur la déviation, elle dérive de la Objet.Equals(Object) page MSDN:
J'ai trouvé une autre référence, c'est l' .NET Type Anonyme de mise en œuvre. Pour un type anonyme avec un int et un double que les propriétés j'ai démonté le code C# suivant:
Je n'ai qu'à tirer de cette classe
Puis de mettre en œuvre la méthode abstraite comme ce