Comment dois-je aller sur la mise en œuvre Object.GetHashCode () pour l'égalité complexe?

StackOverflow https://stackoverflow.com/questions/1072058

Question

En fait, je donne les résultats suivants jusqu'à présent:

class Foo {
    public override bool Equals(object obj)
    {
        Foo d = obj as Foo ;
        if (d == null)
            return false;

        return this.Equals(d);
    }

    #region IEquatable<Foo> Members

    public bool Equals(Foo other)
    {
        if (this.Guid != String.Empty && this.Guid == other.Guid)
            return true;
        else if (this.Guid != String.Empty || other.Guid != String.Empty)
            return false;

        if (this.Title == other.Title &&
            this.PublishDate == other.PublishDate &&
            this.Description == other.Description)
            return true;

        return false;
    }
}

Alors, le problème est le suivant: j'ai un champ non obligatoire Guid, qui est un identifiant unique. Si ce n'est pas réglé, je dois essayer de déterminer l'égalité fondée sur des mesures moins précises comme une tentative de déterminer si deux objets sont égaux. Cela fonctionne très bien, mais il fait désordre ... Comment dois-je GetHashCode() aller à ce sujet? Une mise en œuvre naïve serait quelque chose comme:

public override int GetHashCode() {
    if (this.Guid != String.Empty)
        return this.Guid.GetHashCode();

    int hash = 37;
    hash = hash * 23 + this.Title.GetHashCode();
    hash = hash * 23 + this.PublishDate.GetHashCode();
    hash = hash * 23 + this.Description.GetHashCode();
    return hash;
}

Mais quelles sont les chances des deux types de hachage entrant en collision? Certes, je ne m'y attendais pas à 1 in 2 ** 32. Est-ce une mauvaise idée, et si oui, comment dois-je faire?

Était-ce utile?

La solution

Je ne pense pas qu'il y ait un problème avec l'approche que vous avez choisi d'utiliser. Se soucier « trop » sur les collisions de hachage est presque toujours une indication de plus de repenser le problème; tant que le hachage est très susceptible d'être différent, vous devriez être bien.

En fin de compte, vous voudrez peut-être envisager de quitter le Description de votre hachage de toute façon s'il est raisonnable de penser que la plupart des objets de temps peuvent être distingués en fonction de leur date de titre et publication (livres?).

Vous pouvez même envisager sans tenir compte du GUID dans votre fonction de hachage tout à fait, et ne l'utiliser que dans la mise en œuvre pour lever l'ambiguïté Equals le cas improbable (?) Des affrontements de hachage.

Autres conseils

Une très facile méthode de code de hachage href="http://mindprod.com/jgloss/hashcode.html#CALCULATING" pour les classes personnalisées est XOR chacun des les codes de hachage ensemble de champs. Il peut être aussi simple que cela:

int hash = 0;
hash ^= this.Title.GetHashCode();
hash ^= this.PublishDate.GetHashCode();
hash ^= this.Description.GetHashCode();
return hash;

À partir du lien ci-dessus :

  

XOR a les propriétés suivantes belles:

     
      
  • Il ne dépend pas de l'ordre de calcul.
  •   
  • Il n'a pas d'bits « déchets ». Si vous changez même un peu dans l'un des composants, la valeur finale changera.
  •   
  • Il est rapide, un seul cycle même sur l'ordinateur le plus primitif.
  •   
  • Il conserve une distribution uniforme. Si les deux pièces que vous combinent sont uniformément répartis de façon sera la combinaison soit. En d'autres termes, il ne tend pas à réduire la portée de la digestion dans une bande plus étroite.
  •   

XOR ne fonctionne pas bien si vous vous attendez à avoir des valeurs en double dans vos champs comme valeurs en double s'annulent quand XORé. Puisque vous hachant ensemble trois domaines indépendants qui ne devrait pas être un problème dans ce cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top