2010-07-23 21 views
13

Salut à tous, J'ai lu la meilleure façon d'implémenter le remplacement de GetHashCode() pour les objets dans .NET, et la plupart des réponses que je rencontre impliquent des numéros de monging des membres qui sont types numériques à venir avec une méthode. Le problème est, j'ai un objet qui utilise une chaîne alphanumérique comme clé, et je me demande s'il y a quelque chose de fondamentalement faux en utilisant simplement un ID interne pour les objets avec des chaînes comme des clés, quelque chose comme ceci?GetHashCode() avec les clés de chaîne


// Override GetHashCode() to return a permanent, unique identifier for 
// this object. 
static private int m_next_hash_id = 1; 
private int m_hash_code = 0; 
public override int GetHashCode() { 
    if (this.m_hash_code == 0) 
    this.m_hash_code = <type>.m_next_hash_id++; 
    return this.m_hash_code; 
} 

Y at-il une meilleure façon de trouver un code de hachage unique pour un objet qui utilise une chaîne alphanumérique comme clé? (Et non, les parties numériques de la chaîne alphanumérique ne sont pas uniques, certaines de ces chaînes ne contiennent pas de nombres du tout.) Toutes les pensées seraient appréciées!

Répondre

19

Vous pouvez appeler GetHashCode() sur les valeurs non numériques que vous utilisez dans votre objet.

private string m_foo; 
public override int GetHashCode() 
{ 
    return m_foo.GetHashCode(); 
} 
+0

Mais que se passe-t-il si cette chaîne change? Par exemple, je pourrais créer un nouvel objet Utilisateur avec: User foo = new User(); et le constructeur définit User.Id = "". Plus tard, si je dis User.Id = "A12345"; et je retourne this.Id.GetHashCode() comme le résultat de foo.GetHashCode(), n'aura-t-il pas changé, violant le principe que le code de hachage d'un objet ne devrait jamais changer? –

+6

L'objet a été modifié. Le code de hachage * doit également changer *. –

+0

@King - il existe plusieurs façons d'utiliser les codes de hachage. La valeur du code de hachage doit toujours être la même pour la même valeur de départ. Si votre valeur est mutable, vous devez stocker le hashcode résultant et le renvoyer à la place lorsque 'GetHashCode()' est appelé. –

0

Oui, un meilleur moyen serait d'utiliser le hashcode de la chaîne que vous avez déjà. Si la chaîne alphanumérique définit l'identité de l'objet que vous avez, son hashcode fera très bien l'affaire du hashcode de votre objet.

L'idée d'incrémenter un champ statique et de l'utiliser comme hashcode est mauvaise. Le code de hachage devrait avoir une distribution égale à travers l'espace des valeurs possibles. Cela garantit, entre autres choses, qu'il fonctionnera bien lorsqu'il est utilisé comme clé dans une table de hachage.

0

Je crois que vous voulez généralement GetHashCode() retourner quelque chose qui identifie l'objet par sa valeur, plutôt que c'est par exemple, si je comprends bien l'idée ici, je pense que votre méthode assurerait GetHashCode() sur deux objets différents avec des valeurs équivalentes seraient renvoyer des hachages différents simplement parce qu'ils sont des instances différentes.

GetHashCode() est destiné à renvoyer une valeur qui vous permet de comparer deux valeurs d'objets, pas leurs références.

2

Les codes de hachage ne doivent pas nécessairement être uniques. Si votre implémentation Equals est correcte, vous pouvez renvoyer le même code de hachage pour deux instances. La logique m_next_hash_id est rompue, car elle permet à deux objets d'avoir des codes de hachage différents, même s'ils sont égaux.

MSDN donne un bon jeu d'instructions sur la façon de mettre en œuvre Equals et GetHashCode. Several of the examples here implémenter GetHashCode en termes de codes de hachage des champs d'un objet

18

Ceci n'est pas un bon motif pour générer des hachages pour un objet.

Il est important de undunderstand dans le but de GetHashCode() - c'est un moyen de générer une représentation numérique des propriétés d'identification d'un objet. Les codes de hachage sont utilisés pour permettre à un objet de servir de clé dans un dictionnaire et, dans certains cas, d'accélérer les comparaisons entre types complexes.

Si vous générez simplement une valeur aléatoire et l'appelez un code de hachage, vous n'avez aucune répétabilité. Une autre instance avec les mêmes champs clés aura un code de hachage différent, et violera le comportement attendu par des classes comme HashSet, Dictionary, etc.

Si vous avez déjà un membre de chaîne d'identification dans votre objet, renvoyez simplement son code de hachage .

Le documentation on MSDN for implementers of GetHashCode() est un incontournable pour toute personne qui planifie sur le remplacement de cette méthode:

Notes Implementers

Une __gVirt_NP_NN_NNPS<__ fonction de hachage est utilisé pour générer rapidement un nombre (hachage code) qui correspond à la valeur d'un objet. Les fonctions de hachage sont généralement spécifiques à chaque type et, pour l'unicité , doivent utiliser au moins l'un des champs d'instance comme entrée.

Une fonction de hachage doit avoir les propriétés suivantes :

Si deux objets se comparent égale, le procédé GetHashCode pour chaque objet doit retourner la même valeur. Cependant, si deux objets ne se comparent pas comme égale, les méthodes GetHashCode pour l'objet deux n'ont pas à retourner valeurs différentes.

La méthode GetHashCode pour un objet doit retourner systématiquement le même code de hachage tant qu'il n'y a pas de modification à l'état d'objet qui détermine la valeur de retour de la méthode Equals objet de . Notez que ce est vrai uniquement pour l'exécution en cours d'une application, et qu'un code de hachage différent peut être renvoyé si l'application est réexécutée. Pour obtenir les meilleures performances, une fonction de hachage doit générer une distribution aléatoire pour toutes les entrées.

Par exemple, la mise en œuvre de la méthode GetHashCode fournie par la classe String retourne hachage identique codes pour les valeurs de chaîne identiques. Par conséquent, deux objets String renvoient le même code de hachage s'ils représentent la même valeur de chaîne. En outre, la méthode utilise tous les caractères de la chaîne pour générer une sortie raisonnable au hasard distribués, même lorsque l'entrée est regroupée dans certaines gammes (par exemple, de nombreux utilisateurs pourraient avoir des chaînes qui ne contiennent que le inférieur 128 ASCII caractères, même si une chaîne peut contenir l'un des 65 535 caractères Unicode ).