9
votes

Pourquoi GetHashCode est-il en classe d'objets?

pourquoi gethashcode fait partie de la classe d'objets ? Seule une petite partie des objets des classes sont utilisées comme clés dans les tables de hachage. Ne serait-il pas préférable d'avoir une interface distincte qui doit être mise en œuvre lorsque nous voulons que des objets de la classe servent de clés dans la table de hachage.

Il doit y avoir une raison pour laquelle l'équipe de MS a décidé d'inclure cette méthode dans la classe d'objet et de la rendre disponible "partout".


1 commentaires

Je soupçonne que cela a été modélisé après java.lang.Object 's hashcode () avant .net a commencé à utiliser des interfaces beaucoup (notez que gethashcode va tout le chemin du retour à .NET 1.0).


7 Réponses :


0
votes
  1. alors tout peut être clé. (Sorte)
  2. de cette façon hashtable peut prendre un objet vs quelque chose qui implémente ihashable par exemple.
  3. pour conduire une comparaison d'égalité simple.

    sur des objets qui ne le mettent pas directement sur les valeurs par défaut du code de hachage interne de .NET, que je pense soit un identifiant unique pour l'instance d'objet ou un hachage de l'empreinte mémoire qu'il occupe. (Je ne me souviens pas que le réflecteur .NET ne peut pas dépasser le composant .NET de la classe).


2 commentaires

Gethashcode n'a rien à voir avec les comparaisons - c'est un problème distinct.


A.GetHashCode () est égal à A.GethashCode (), mais B.GethashCode () peut être égal à A.GethashCode (). C'est une très mauvaise idée de l'utiliser "pour conduire une comparaison simple de l'égalité".



3
votes

Seule une petite partie des objets des classes sont utilisées comme clés dans les tables de hachage

Je dirais que ce n'est pas une déclaration vraie. De nombreuses classes sont souvent utilisées comme clés dans les tables de hachage - et les références d'objet elles-mêmes sont très souvent utilisées. Avoir la mise en œuvre par défaut de gethashcode existe dans System.Object signifie que tout objet peut être utilisé comme clé, sans restrictions.

Cela semble beaucoup plus agréable que de forcer une interface personnalisée sur des objets, juste pour pouvoir les hacher. Vous ne savez jamais quand vous devrez peut-être utiliser un objet comme clé dans une collection hachée.

Ceci est particulièrement vrai lorsque vous utilisez des éléments tels que hashset - dans ce cas, souvent, une référence d'objet est utilisée pour le suivi et l'unicité, pas nécessairement comme une "clé". Le hachage avait-il requis une interface personnalisée, de nombreuses classes deviendraient beaucoup moins utiles.


4 commentaires

Alors pourquoi est-ce écrit dans le gethascode Page : "... La mise en œuvre par défaut de cette méthode ne doit pas être utilisée comme identifiant d'objet unique à des fins de hachage"?


Pourquoi quoi que quelque chose devienne moins utile? Vous pourriez simplement spécifier un IéqualityComparer qui pourrait être "comparer par référence". En effet, c'est ce que équalitycomparer .default pourrait faire. Voir ma réponse pour plus de détails.


@Jon: TRUE - cela nécessiterait de la spécifier séparément, mais cela pourrait être fait assez facilement - mon point était que je voudrais m'opposer à l'objet lui-même de mettre en œuvre l'interface - mais la spécifierait séparément irait bien.


@Reedcopsey je ne pouvais pas être en désaccord plus. Parmi toutes les classes de tous de .NET et tous les projets fabriqués par les utilisateurs, peut-être 0,0001% ont besoin de hachage / égalité. En .NET elle-même, le nombre primitives / intégré environ 15-20 types (l'INTS, la chaîne, les énumjets, peut-être que même les décimales / flotteurs / dates / temps). Dans la plupart des autres projets, ce sont généralement les entités, qui hérimentent généralement d'entitébase de toute façon pouvant mettre en œuvre l'égalité / hachage appropriés.



0
votes

gethashcode est en objet de sorte que vous puissiez utiliser quelque chose comme clé dans une haquetable, une classe de conteneurs de base. Il fournit une symétrie. Je peux mettre n'importe quoi dans une arrayliste, pourquoi pas une hache de hashtable?

Si vous avez besoin de classes à implémenter ihashable, alors pour chaque classe scellée qui ne s'applique pas ihashable, vous allez écrire des adaptateurs lorsque vous souhaitez l'utiliser comme clé qui incluent la capacité de hachage. Au lieu de cela, vous l'obtenez par défaut.

Les hashcodes sont également une bonne deuxième ligne pour la comparaison sur l'égalité d'objet (la première ligne est l'égalité du pointeur).


0 commentaires

1
votes

Il permet à n'importe quel objet d'être utilisé comme clé par "Identity". Ceci est bénéfique dans certains cas et nocifs dans aucun. Alors, pourquoi pas?


4 commentaires

Parce que dans la comparaison en pourcentage, seuls, très peu d'objets de classe sont utilisés comme touches. Selon votre réponse, on peut conclure pourquoi nous avons besoin d'une interface icomparable, incluons la comparète dans la classe d'objets :)


@Incognito: Non, on ne peut pas conclure que Icomarable est inutile, car il n'est pas possible de définir une implémentation sensible de comparète pour tous les objets. Une relation d'équivalence basée sur identité a beaucoup de sens, et il est facile de définir une méthode gethashcode cohérente avec cette définition. On ne peut pas dire la même chose pour comparèteo . Lors de l'utilisation en tant que touches de carte est limitée, la création d'un Hashset basé sur l'identité est fréquenter de nombreux types et serait exclu sans un moyen de calculer un code de hachage pour tout type d'objet.


De même, @erickson, Equals / GetHashCode n'est pas sensible pour la plupart des objets.


Je souhaite que Microsoft ait été plus cohérent dans les comportements de équivaut à des substitutions , même au détriment de la création de surcharges moins cohérents (puisque est égal à des implémentations sont nécessaires pour définir une relation d'équivalence et Étant donné que les surcharges de types équivalent ne peuvent pas définir une relation d'équivalence, il ne faut pas s'attendre à ce qu'ils se comportent de la même manière). Je souhaite également qu'il existait une manière standard via laquelle un objet pourrait indiquer s'il pouvait concevoir tout autre objet auquel il se considère comme égal (cette fonction renvoie par défaut FAUX).



0
votes

Si chaque classe a gethashcode, vous pouvez mettre chaque objet dans un hachage. Imaginez que vous ayez un pour utiliser des objets tiers (que vous ne pouvez pas modifier) ​​et souhaitez-vous les mettre en hachage AB. Si ces objets ne vous ont pas implémenté, ihashable vous ne pouviez pas le faire. C'est évidemment une mauvaise chose;)


1 commentaires

Oui, vous pouvez simplement dire à la table de hachage à utiliser via IequalityComparer . Très simple.



19
votes

C'était une erreur de conception copiée de Java, imo.

Dans mon monde parfait:

  • tostring serait renommé toDebugstring pour définir des attentes de manière appropriée
  • est égal à et gethashcode serait parti
  • Il y aurait un RéférencesLalityComalcomparer de IequalityComparer : La partie égale à ceci est facile pour le moment, mais il n'y a aucun moyen d'obtenir un "original" code de hachage s'il est remplacé par
  • Les objets n'auraient pas les moniteurs associés à eux: moniteur aurait un constructeur et entrez / quitter etc. serait des méthodes d'instance.

    Égalité (et donc hachage) causer des problèmes dans les héritiers d'héritage en général - tant que vous pouvez toujours spécifier le type de comparaison que vous souhaitez utiliser (via Iéqualitycomparer ) et les objets peuvent implémenter IEQUATIF S'ils le souhaitent, je ne vois pas pourquoi il devrait être sur objet . EqualitComparer .default pourrait utiliser l'implémentation de référence si t n'a pas implémenté iéquatif et reporter les objets autrement. La vie serait agréable.

    ah bien. Pendant que je suis à cela, Tarra Covariance était une autre erreur de plateforme. Si vous voulez des erreurs de langue en C #, je peux commencer une autre déclaration mineure si vous le souhaitez;) (C'est encore loin ma langue préférée, mais il y a des choses que je souhaite avoir été faite différemment.)

    J'ai blogué à propos de cette < / a> ailleurs, btw.


10 commentaires

Oui, pourquoi ne pas ouvrir une autre discussion de fil pour les erreurs de langue. Je crois qu'il y aura d'autres que vous aimez noter quelque chose comme GetHashCode "erreur" :)


@Incognito: Il y a une "top 5 dans votre langue préférée" question autour de quelque part ...


@Jonskeet Je dirais que TODEBUNTSString n'est pas bon non plus. Le débogage doit être séparé du code de production. En tant que tel, les attributs sont une bien meilleure solution. ("le" parce qu'ils sont déjà disponibles)


@ M.ta: Quels attributs parlez-vous? Je voudrais probablement cahnge this à "Todiagnosticstring" ou quelque chose de similaire - ce n'est pas interactif débogage, certainement.


@jonskeet System.Diagnostics Namespace - RTM :)


@ M.ta: System.Diagnostics contient de nombreux attributs, et il n'est toujours pas clair que l'un d'entre eux correspond à "Je souhaite avoir une représentation de chaîne de diagnostic de cet objet à inclure dans les journaux".


@Jonskeet MSDN.MicRosoft.com/en-us/Library/ ...


@ M.A: À droite - Juste en disant "DebuggerDisplayAttribute" Il y a plusieurs commentaires aurait été plus utile. Cependant, cela n'aide toujours pas (sans effort significatif) pour les diagnostics non débogués, conformément à mes commentaires ultérieurs.


@ Jonskeet Je ne me suis pas souvenu moi-même, je devais la regarder pour vous. En ce qui concerne les journaux - peut-être que cela devrait être une implémentation d'interface, alors? IdiagnosticstringProvider ou quelque chose. La journalisation est une utilisation en cours de production valide; Le débogueur peut ensuite utiliser cette interface ou cette attribut, selon la priorité majeure. La raison pour laquelle il devrait s'agir d'une interface est que tous les objets n'ont pas un état significatif qui peut être émis dans une chaîne de diagnostic. (Tout comme tous les objets ne sont pas équitables / hachables)


@ Mr.ta: Oui, je serais raisonnablement satisfait de cela comme une interface ... bien que la douleur de quelque chose de ne pas avoir de production de diagnostic utile n'est pas aussi grande que d'autres choses.



0
votes

Juste une supposition, mais le collecteur des ordures peut stocker des hashtables de certains objets interne (peut-être garder une trace des objets finalisables), ce qui signifie que tout objet doit avoir une clé de hachage.


0 commentaires