En lisant Jeffrey Richter's CLR via C # 4ème édition (Microsoft Press) , l'auteur à un point indique que, tandis que Cela me frappe comme très impair: tous les L'objet non nul du même type serait égal em> par défaut? Donc, à moins que la nervation: tous les instances em> d'un type sont égales (par exemple, tous vos objets de verrouillage sont égaux) et renvoyez le même code de hachage. Et en supposant que le Je pense que l'idée de choses étant égale si c'est exactement la même chose (identité) est une meilleure idée que de rendre tout simplement égal à moins que possible. Mais il s'agit d'une 4ème édition du livre bien connu publiée par Microsoft, il doit donc y avoir du mérite à cette idée. J'ai lu le reste du texte mais je ne pouvais pas m'empêcher de me demander: pourquoi l'auteur le suggère-t-il? Qu'est-ce que j'oublie ici? Quel est le grand avantage de la mise en œuvre de Richter sur l'objet actuel. Mise en œuvre? EM> P> P> objet.equals code> vérifie actuellement l'égalité d'identité, Microsoft aurait dû mettre en œuvre la méthode comme celle-ci :
== code> sur
objet code> vérifie toujours l'égalité de référence, cela signifierait que
(A == B)! = A. / B) Code> qui serait aussi étrange. P>
4 Réponses :
Le courant Je pense que cela est parfaitement acceptable pour une implémentation de base em>. Je ne penserais certainement pas que c'est faux ou incomplet. P>
Exemple de Richter 1 sup> que vous citez est également parfaitement légitime pour le système de base.Object em>. La question avec sa mise en œuvre est qu'il faut sans doute être déclarée abstraite 2 sup> - avec sa méthode, vous vous retrouverez avec un (juste pour une référence facile, voici la mise en œuvre par défaut telle que publiée dans le livre) P>
2: Bien sûr signifie qu'il n'y aurait pas de mise en œuvre de base, ce qui serait bon car il aurait été peu fiable. sup> p> est égal () code> fait ce que l'on appelle un comparateur peu profond (ou un comparateur de référence), puis ne vérifie plus si les références diffèrent. P>
peu fiable () code> sur des objets dérivés si vous ne remplacez pas si vous ne remplacez pas Il (parce que
égale () code> est censé faire un comparateur profond). Avoir à remplacer cette méthode sur tous les objets dérivés serait beaucoup de travail, la manière Microsoft est donc meilleure
true code> entraînerait un comportement assez intéressant si les gens ont oublié de le remplacer. ). p>
p>
1: Richter est un homme intelligent qui connaît ses trucs et je ne discuterais pas généralement avec quoi que ce soit, il dit. Vous devez comprendre que les ingénieurs de la SP auraient dû réfléchir longuement et dur de beaucoup de choses, sachant qu'ils n'avaient pas la flexibilité de la possibilité de se tromper, puis de fixer des choses plus tard. Peu importe la raison, les gens vont toujours les deviner à une date ultérieure et proposera des opinions alternatives. Cela ne signifie pas que l'original est faux ou l'alternative est fausse - cela signifie simplement qu'il y avait une alternative. Sup>
p>
Jeffery Richter parle de valeur em> égalité sur identité em> égalité. p>
Spécifiquement, vous demandez: P>
Donc, à moins de remplacement: toutes les instances d'un type sont égales? P>
blockQuote>
La réponse est Ainsi, pour la plupart des classes, il devrait être remplacé par une comparaison d'attributs par attribut pour déterminer l'égalité. Pour d'autres classes qui sont vraiment basées sur l'identité (comme des verrous), il devrait être remplacé pour utiliser la même technique que celle utilisée aujourd'hui. P>
La clé est que cela doit être remplacé dans presque tous les cas, et cela seul est suffisamment difficile, maladroit et erroné - sujette que c'est probablement pourquoi Microsoft n'a pas utilisé cette approche. P>
Quel est l'avantage de la valeur-égalité sur l'égalité des identités? C'est que si deux objets différents ont les mêmes valeurs / contenus, ils peuvent être considérés comme «égaux» à des fins de comparaison dans des cas tels que les clés d'un objet dictionnaire. p>
ou considérez la matière des chaînes dans .NET, qui sont en fait des objets, mais sont traités beaucoup comme des valeurs à des niveaux plus élevés (en particulier dans VB.NET). Cela pose un problème lorsque vous souhaitez comparer deux chaînes pour l'égalité, car 99% du temps que vous ne vous souciez pas vraiment si ce sont des objets différents les instances em>, vous ne vous souciez que si elles contiennent le même texte. SO .NET doit s'assurer que c'est la manière dont la comparaison des chaînes fonctionne réellement, même si elles sont vraiment des objets. P>
En fait, je voulais dire: Quel est le grand avantage de la mise en œuvre de Richter sur l'objet actuel. Mise en œuvre? I>
@VirtLink L'avantage est que cela explique efficacement les forces i> les personnes à remplacer est égal à code> afin d'obtenir une égalité qui signifie quelque chose, au lieu d'avoir une implémentation par défaut qui est rarement souhaitée, mais apparaît sembler approprié comme pour les nouveaux programmeurs. Cela revient à ce que les objets nécessitent très rarement une égalité de référence et souhaitent presque toujours utiliser l'égalité de valeur, mais la mise en œuvre par défaut est l'égalité de référence.
Surtout que la plupart des langues ont un autre opérateur / méthode spécifiquement pour l'égalité de référence / identité, comme est code>.
devinez: le comportement actuel de Le motif principal (seulement?) de cette méthode d'exister est de permettre la recherche d'éléments dans les collections en prétendant être "==" Mise en œuvre. Donc, dans la plupart des cas pratiques, cette mise en œuvre se comporte de manière inattendue (à l'exception de l'affaire lorsque vous souhaitez trouver si une instance particulière est déjà dans la collection) et vous forcez à vous fournir des fonctions de comparaison personnalisées ... P>
probablement c'est une méthode d'objet parce que pour des raisons techniques. C'est à dire. Pour le tableau / dictionnaire, il peut être plus rapide d'assumer que tous les objets ont sans doute, il ne doit pas être sur un objet du tout et nécessitera simplement des classes pouvant être stockées dans des collections pour mettre en œuvre une partie de l'interface objet.equals code> n'est pas ce que la plupart des gens considèrent comme "égaux". p>
égal code> /
gethash code> au lieu de vérifier quelque chose sur l'objet pour activer la fonctionnalité "Rechercher". P>
icomparable code>. p>
Vous voulez dire iequaltable code> pas
icomparable code>. De nombreux objets peuvent être égaux ou non égaux sans pouvoir déterminer lequel est plus grand ou moins que l'autre.
Si on est invitée à faire une liste de tous des objets d'arbitraires identifiablement distincts, et n'a aucune indication de ce que les objets sont ou ce qu'ils seront utilisés, seuls les moyens universellement applicables de tester si deux Les références doivent être considérées comme indiquant que les objets identifiablement distincts sont Par exemple, si deux instances de Dans la plupart des cas, des objets qui existent pour contenir des données immuables doivent être considérés comme identiques si les données qu'ils détiennent sont identiques. Les objets qui existent pour contenir des données mutables ou qui existent pour servir de jetons d'identité doivent généralement être considérés comme distincts les uns des autres. Étant donné que l'on peut définir un Pour utiliser une analogie du monde réel, supposons que l'on reçoive deux morceaux de papier, chacun avec un numéro d'identification de véhicule écrit dessus et est demandé si la voiture identifiée par le premier morceau de papier est identique à la voiture identifiée. par la seconde. Si les deux glissades de papier ont le même Vin, il est clair que la voiture identifiée par la première est la même que celle identifiée par la seconde. S'ils ont des Vins différents, cependant, à l'exclusion de toute possibilité étrange d'une voiture ayant plus d'un VIN, puis identifient différentes voitures. Même si les voitures ont la même marque et le même modèle, les packages d'options, le schéma de peinture, etc. Ils seraient toujours différentes voitures. Une personne qui a acheté on ne serait pas autorisée à commencer arbitrairement à l'aide de l'autre. Il peut parfois être utile de savoir si deux voitures ont actuellement les mêmes packages d'options, etc. Mais si c'est ce que l'on veut savoir, c'est ce que l'on devrait demander. P> objet.equaux (objet) code>. Deux références
x code> et
y code> doivent être considérées comme identifiables-distinctes si elles sont modifiées une ou plusieurs références qui pointent actuellement sur
x code> de sorte qu'ils pointent sur < Code> y code> serait probablement modifier le comportement du programme. P>
String CODE> contiennent tous les deux tout le texte de guerre et paix i>, ponctués et formatés de manière identique, on pourrait probablement remplacer certaines ou toutes les références à la d'abord avec des références à la seconde, ou vice versa, avec peu ou aucun effet sur l'exécution du programme au-delà du fait qu'une comparaison entre deux références qui pointent sur la même instance peut être trouvée beaucoup plus rapidement que deux références qui ne peuvent pas faire deux références qui pointent. à différentes chaînes contenant des caractères identiques. P>
égalleur sur mesure code> qui considère comme des objets équivalents qui ne sont pas totalement équivalents (par exemple, un comparateur de chaîne insensible à une casse), et étant donné que le code nécessitant une certaine définition de l'équivalence plus large que une équivalence stricte devrait généralement savoir quels types il travaille avec et quelle définition de l'équivalence est appropriée, il est généralement préférable d'avoir
objet.equals code> signaler des objets comme étant différent à moins qu'ils soient conçus pour être substituables (comme cela être, par exemple, des cordes). p>
Donc, si je vous comprends correctement: Sauf si il est logique que l'objet de l'objet de remplacer est égal à code> pour effectuer une vérification de l'égalité de valeur, vous acceptez que l'objet
par défaut code> devrait ne pas retourner
true code> mais que l'égalité de référence vérifie-t-elle actuellement.
@VirtLink: précisément. Une faiblesse en Java, qui transporte en grande partie à .NET, est qu'il n'y a pas de distinction entre les références d'objet qui sont conservées pour encapsuler l'identité i> de leur cible, ce qui encapsule contentement mutable i > Celui-ci encapsule i> i> et qui encapsule ni i> [encapsulant juste du contenu immuable, autre que l'identité]. Le type de base objet code> n'a aucun contenu - tout ce qu'il a une identité, c'est donc la seule base sensible à la comparaison. D'autres types tels que
chaîne code> ont un contenu immuable, mais aucune identité forte.
@VirtLink: Les objets de types mutables ont généralement une identité forte, sauf indication non (1) qu'il n'existe qu'une référence persistante (autre qu'une variable locale), n'importe où dans l'univers, ou (2) aucune référence ne sera jamais détenue par quelque chose qui va muté l'objet en question. Seulement si l'une de ces conditions s'applique au sens qu'il serait logique de considérer l'égalité de valeur plutôt que de l'égalité de référence, et il n'y a aucun moyen qu'un type de classe puisse savoir que l'un d'entre eux s'applique. Notez cependant que le n ° 1 s'applique aux types de valeur non complets et s'applique généralement aux types de valeur en boîte.
Bien que l'identité puisse fonctionner par défaut, la comparaison sur l'égalité par défaut n'est apparemment pas très significative. Certains parlent même de faire égale code> résumé. J'irais même aussi loin que d'indiquer que code> objet code> ne doit pas avoir de
égale code> ou un
gethashcode code>. Les deux devraient être dans
Iequatable
Iequatable
RéférencesAsalityComParer code>). EDIT: HMM .. Apparemment Jon Skeet pense aussi.
@VirtLink: Iequatable
égale code> tel que
x.equals (y) code> implique
x code> est substituable pour
y code>, alors c'est possible. Pour rédiger un interne générique
faimérer code> cache pour accélérer les choses telles que la désérialisation (si une instance nouvellement déséréalisée correspond à une performance préexistante, des performances peuvent être améliorées en supprimant le nouveau et en utilisant l'ancien à la place). Le fait que certains types de cadre ...
... Définir est égal à code> pour signifier quelque chose que l'équivalence sémantique complique un peu les choses, mais cela ne signifie pas qu'une méthode universellement disponible pour tester si deux références sont équivalentes ne serait pas significative.
Bien que sa mise en œuvre ne soit pas claire, le commentaire explique correctement? Les objets sont égaux que si les champs correspondent.
+1 pour une question fantastique. J'ai lu le livre et honnêtement, je n'ai pas non plus vu l'avantage de la mettre en œuvre de cette façon.