La surcharge de l'opérateur== rapport est Égal à()
Je suis en train de travailler sur un projet C# sur lequel, jusqu'à présent, j'ai utilisé des objets immuables et les usines afin de s'assurer que les objets de type Foo
peut toujours être comparé pour l'égalité avec ==
.
Foo
les objets ne peut pas être changé une fois créé, et l'usine renvoie toujours le même objet pour un ensemble donné d'arguments. Cela fonctionne très bien, et tout au long de la base de code, nous supposons que ==
travaille toujours pour la vérification de l'égalité.
Maintenant, j'ai besoin d'ajouter quelques fonctionnalités qui présente un cas limite pour lequel cela ne fonctionne pas toujours. La meilleure chose à faire est de surcharge operator ==
pour ce type, de sorte qu'aucun autre code dans le projet qui doit changer. Mais ce qui me frappe comme une odeur de code: surcharge operator ==
et pas Equals
semble juste bizarre, et je suis habitué à la convention qui ==
contrôles de référence de l'égalité, et Equals
vérifie objet d'égalité (ou peu importe le terme).
Est-ce une préoccupation légitime, ou devrais-je simplement aller de l'avant et de surcharge operator ==
?
- D'ailleurs, vb.net interdit l'utilisation de ses
=
et<>
opérateurs d'égalité pour les types qui ne sont pas explicitement les surcharges; pour vérifier la référence de l'égalité, on utiliseIs
ouIsNot
, qui, essentiellement, <i>toujours</i> vérifier la référence de l'égalité (à l'exception notable lorsque l'on compare les types nullables pourNothing
).
Vous devez vous connecter pour publier un commentaire.
Je crois que la norme est que pour la plupart des types .Est égal à des vérifications de l'objet de la similitude et l'opérateur
==
contrôles de référence de l'égalité.Je crois que la meilleure pratique est que pour immuable types, opérateur
==
devrait être la vérification de la similitude, ainsi que.Equals
. Et si vous voulez savoir si elles sont vraiment le même objet, l'utilisation.ReferenceEquals
. Voir le C#String
classe pour un exemple de cette.a != b
mais les classes de Collection pensent qu'ils sont des doublons?Il y a une grande différence entre surcharge
==
et primordial égal à Égal.Lorsque vous avez l'expression
La méthode qui sera utilisée pour comparer les variables x et y est décidé à compiler temps. C'est la surcharge d'opérateur. Le type utilisé lors de la déclaration de x et y est utilisé pour définir la méthode utilisée pour comparer. Le type réel à l'intérieur de x et y (c'est à dire, une sous-classe ou de l'interface de mise en œuvre) n'est pas pertinente. Considérons l'exemple suivant.
et suivants
Cela démontre que le type utilisé pour déclarer les variables x et y est utilisé pour déterminer la méthode utilisée pour évaluer ==.
Par comparaison, est Égal à est déterminé à runtime, sur la base du type de la variable x. Égale est une méthode virtuelle sur l'Objet que d'autres types peuvent remplacer. Par conséquent, les deux exemples suivants évalués à la valeur true.
et suivants
operator==
dépendent du type à l'exécution, j'ai défini une surcharge de l'opérateur dans la classe de base qui a appeléEquals()
. A travaillé comme un charme. (Puis j'ai refait le modèle d'objet et déchira l'ensemble de la chose. Mais c'est une autre histoire.)==
est une commune de l'idiome. Juste parce que C# bases de toutes les entités àobject
ne signifie pas que nous devrions abandonner le langage pour éviter que la situation dans ce post. Plutôt, il devient une bonne pratique à utiliser.Equals()
lorsqu'il est nécessaire de comparer, au sommet de la hiérarchie.''
etEquals
est très dangereux de l'OMI. Ils doivent être programmés pour faire la même chose et vous pouvez fournir des implémentations différentes deIEqualityComparer
d'offrir des alternatives égalité des implémentations.X
etY
ne se comportent pas de la sémantique à l'identique est une odeur de code bien pire que d'avoirX.Equals(Y)
retour à un résultat différent deX==Y
. Entre autres choses, le fait que le type de contrainte peut se produire avant que les opérandes sont comparés avec==
signifie queX==Y
ne peut pas très bien définir une relation de récurrence. Par exemple,123456789123456789 == 123456789123456789.0
rendements vrai, de même que123456789123456788 == 123456789123456789.0
, mais123456789123456789 == 123456789123456788
renvoie false. L'idée queEquals(Object)
et==
devrait se comporter de la même...Equals(Object)
dansDecimal
,Single
, etDouble
. À mon avis, l'égalité-tester l'opérateur doit vérifier si les deux paramètres sont identiques dans la façon le plus souvent associée avec le type, tandis que laEquals
méthode d'essai pour les plus forts, l'équivalence. Je considère1.0m
être égal, mais pas l'équivalent,1.00m
.==
de simplement appelerReferenceEquals
, puisque c'est ce que l'==
opérateur de test de toute façon. Comme lorsqu'il doit différer deEquals
, j'ai donné un exemple; peut-être que j'ai besoin de préciser un peu plus. Lorsque vous travaillez avec immuables classes, on va souvent créer de nombreux objets identiques--pas délibérément, mais souvent parce que l'on arrive à effectuer les mêmes opérations sur les mêmes opérandes. Par exemple, chaque fois que l'un des appelsX.ToString()
lorsque X se trouve être 34, il va créer une nouvelle chaîne de deux caractères contenant les caractères "34".Equals
tels que siX.Equals(Y)
ne retourne true si la classe est attendrait à ce que, à moins que le code externe effectue de référence fondés sur l'égalité des opérations, on pourrait remplacer en toute sécurité de certaines ou de toutes les occurrences de X avec Y, sans aucun effet autre qu'une amélioration de la performance. Par cette définition,1.00m.Equals(1.0m)
, comme le remplacement de1.00m
avec1.0m
pourrait avoir des effets visibles d'autre que de la performance.Il a certainement des odeurs. En cas de surcharge
==
vous devriez assurez-vous que les deuxEquals()
etGetHashCode()
sont également compatibles. Voir la MSDN lignes directrices.Et la seule raison que cela semble OK à tout, c'est que vous décrivez de votre type comme immuable.
Pour immuable types je ne pense pas qu'il n'y a rien de mal à avoir
==
surchargé à l'appui de la valeur de l'égalité. Je ne pense pas que je voudrais remplacer==
sans écraserEquals
à avoir la même sémantique cependant. Si vous ne remplacent==
et besoin de vérifier la référence de l'égalité, pour une raison quelconque, vous pouvez utiliserObject.ReferenceEquals(a,b)
.Voir ce Microsoft article de quelques lignes directrices utiles
Exemple montrant comment mettre en œuvre cette fonction MSFT lignes directrices (ci-dessous). Avis, lors de la substitution est Égal vous devez également remplacer GetHashCode(). Espérons que cela aide les gens.
==
agissent différemment de tous les autres opérateurs n'est pas grande conception, soit... de Soins est nécessaire lors de la combinaison des opérateurs avec polymorphes références.Selon les directives de Microsoft propres meilleures pratiques les résultats de la méthode Equals et le signe égal (==) surcharge doit être le même.
CA2224: Remplacement est égal à la surcharge de l'opérateur est égal à
==
il convient également de remplacer le virtuelEquals
membre, mais l'inverse n'est pas vrai. On ne devrait surcharge==
pour scellé types qui se comportent tout à fait comme les valeurs (de la même façonString
n'), mais il faut souvent remplacerEquals
pour descellés types. Notez que beaucoup de programmeurs s'attendre à ce que l'application de la==
opérateur à tout type de classe autre questring
est un raccourci pour la vérification de la référence à l'égalité.