70 votes

Comment implémentez-vous GetHashCode pour une structure avec deux chaînes

J'ai une structure en C #:

 public struct UserInfo
{
   public string str1
   {
     get;
     set;
   }

   public string str2
   {
     get;
     set;
   }   
}
 

La seule règle est que UserInfo(str1="AA", str2="BB").Equals(UserInfo(str1="BB", str2="AA"))

Comment remplacer la fonction GetHashCode pour cette structure?

69voto

aku Points 54867

MSDN:

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

  • Si deux objets sont considérées comme égales, l' GetHashCode méthode pour chaque objet doit retourner la même valeur. Toutefois, si deux objets ne sont pas considérées comme égales, l' GetHashCode méthodes pour les deux objets n'ont pas à renvoyer des valeurs différentes.
  • L' GetHashCode méthode pour un objet doit constamment revenir par le même code de hachage tant qu'il n'y a pas de modification de l'état de l'objet qui détermine la valeur de retour de l'objet de l' Equals méthode. Notez que ceci n'est vrai que pour l'exécution d'une application, et qu'un autre code de hachage peut être retourné si l'application est exécutée à nouveau.
  • Pour de meilleures performances, une fonction de hachage doit générer une distribution aléatoire pour toutes les entrées.

Prendre en compte de manière correcte est:

return str1.GetHashCode() ^ str2.GetHashCode() 

^ peut être remplacée par une autre opération commutative

27voto

Tomáš Kafka Points 1777

Voir la réponse de Jon Skeet - des opérations binaires comme ^ ne sont pas bonnes, elles génèrent souvent des hashs en collision!

5voto

Joe Points 60749
  1. En règle générale, une façon simple de générer un hashcode pour une classe de XOR de tous les champs de données qui peuvent participer à la création du code de hachage (en faisant attention à vérifier la valeur null comme souligné par d'autres). Cela répond également à un (artificielle?) l'exigence que les hashcodes pour UserInfo("AA", "BB") et UserInfo("BB", "AA") sont les mêmes.

  2. Si vous pouvez faire des hypothèses sur l'utilisation de votre classe, vous pouvez peut-être améliorer votre fonction de hachage. Par exemple, si il est commun pour les str1 et str2 être la même, XOR ne peut pas être un bon choix. Mais si str1 et str2 représenter, dire, nom et prénom, XOR est probablement un bon choix.

Bien que ce n'est clairement pas destiné à être un exemple réel, il peut être intéressant de souligner que: - C'est probablement un mauvais exemple d'utilisation d'une structure: struct doivent normalement avoir de la valeur sémantique, qui ne semble pas être le cas ici. - À l'aide des propriétés avec des organismes de normalisation pour générer un code de hachage est aussi d'avoir des ennuis.

3voto

Jani Hyytiäinen Points 1907

ReSharper suggère ce qui suit:

 public int GetHashCode()
{
    unchecked
    {
        int hashCode;

        // String properties
        hashCode = (hashCode * 397) ^ (str1!= null ? str1.GetHashCode() : 0);
        hashCode = (hashCode * 397) ^ (str2!= null ? str1.GetHashCode() : 0);

        // int properties
        hashCode = (hashCode * 397) ^ intProperty;
        return hashCode;
    }
}
 

397 est un nombre premier de taille suffisante pour provoquer un débordement de la variable résultat et un peu un mélange des bits du hachage, ce qui permet une meilleure distribution des codes de hachage. Sinon, rien de spécial en 397 ne le distingue des autres nombres premiers de même ampleur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X