147 votes

Quel est le rôle de GetHashCode dans le IEqualityComparer<T> dans .NET?

J'essaie de comprendre le rôle de la méthode GetHashCode de l'interface IEqualityComparer.

L'exemple suivant est tiré de MSDN:

using System;
using System.Collections.Generic;
class Example {
    static void Main() {
        try {

            BoxEqualityComparer boxEqC = new BoxEqualityComparer();

            Dictionary<Box, String> boxes = new Dictionary<Box,
                                                string>(boxEqC);

            Box redBox = new Box(4, 3, 4);
            Box blueBox = new Box(4, 3, 4);

            boxes.Add(redBox, "red");
            boxes.Add(blueBox, "blue");

            Console.WriteLine(redBox.GetHashCode());
            Console.WriteLine(blueBox.GetHashCode());
        }
        catch (ArgumentException argEx) {

            Console.WriteLine(argEx.Message);
        }
    }
}

public class Box {
    public Box(int h, int l, int w) {
        this.Height = h;
        this.Length = l;
        this.Width = w;
    }
    public int Height { get; set; }
    public int Length { get; set; }
    public int Width { get; set; }
}

class BoxEqualityComparer : IEqualityComparer<Box> {

    public bool Equals(Box b1, Box b2) {
        if (b1.Height == b2.Height & b1.Length == b2.Length
                            & b1.Width == b2.Width) {
            return true;
        }
        else {
            return false;
        }
    }

    public int GetHashCode(Box bx) {
        int hCode = bx.Height ^ bx.Length ^ bx.Width;
        return hCode.GetHashCode();
    }
}

Ne pas la méthode Equals de la mise en œuvre sera suffisant pour comparer deux objets de Zone? C'est là que nous dira le cadre de la règle utilisée pour comparer les objets. Pourquoi le GetHashCode nécessaire?

Merci.

Lucian

209voto

Acentric Points 3356

Un peu de fond de la première...

Chaque objet .NET est une méthode Equals et une méthode GetHashCode.

La méthode Equals est utilisé pour comparer un objet avec un autre objet à voir si les deux objets sont équivalents.

La méthode GetHashCode génère un entier de 32 bits représentation de l'objet. Depuis il n'y a pas de limite à la quantité d'information d'un objet peut contenir, certains des codes de hachage sont partagés par plusieurs objets - si le code de hachage n'est pas nécessairement unique.

Un dictionnaire est un vraiment cool structure de données métiers plus de mémoire en retour (plus ou moins) à coûts constants pour Ajouter/Supprimer/Obtenir opérations. C'est un mauvais choix pour une itération sur si. En interne, un dictionnaire contient un tableau de seaux, où les valeurs peuvent être enregistrées. Lorsque vous ajoutez une Clé et d'une Valeur d'un dictionnaire, la GetHashCode méthode est appelée sur la Touche. Le hashcode retourné est utilisé pour déterminer l'indice de la seau dans lequel la paire Clé/Valeur doit être stockée.

Lorsque vous souhaitez accéder à la Valeur, vous pouvez passer à nouveau la Touche. La GetHashCode méthode est appelée sur la Touche, et le seau contenant la Valeur est situé.

Lorsqu'un IEqualityComparer est passé dans le constructeur d'un dictionnaire, le IEqualityComparer.D'égal à égal et IEqualityComparer.GetHashCode méthodes sont utilisées à la place des méthodes sur les objets Clés.

Maintenant, pour expliquer pourquoi les deux méthodes sont nécessaires, prenons cet exemple:

BoxEqualityComparer boxEqC = new BoxEqualityComparer(); 

Dictionary<Box, String> boxes = new Dictionary<Box, string>(boxEqC); 

Box redBox = new Box(100, 100, 25);
Box blueBox = new Box(1000, 1000, 25);

boxes.Add(redBox, "red"); 
boxes.Add(blueBox, "blue"); 

À l'aide de la BoxEqualityComparer.Méthode GetHashCode dans votre exemple, deux de ces boîtes ont le même hashcode - 100^100^25 = 1000^1000^25 = 25 - même s'ils ne sont clairement pas le même objet. La raison qu'ils sont de la même hashcode dans ce cas est parce que vous êtes à l'aide de l' ^ (bit à bit OU exclusif) opérateur de manière 100^100 annule laissant zéro, comme le fait 1000^1000. Lorsque deux objets ont la même clé, on appelle ça une collision.

Lorsque nous ajoutons deux paires Clé/Valeur avec le même hashcode à un dictionnaire, ils sont tous deux stockés dans le même seau. Ainsi, lorsque nous voulons récupérer une Valeur, la méthode GetHashCode est appelée sur notre Clé pour localiser le seau. Depuis il n'y a plus d'une valeur dans le seau, le dictionnaire passe en revue toutes les paires Clé/Valeur dans le seau de l'appel de la méthode Equals sur les Touches pour trouver la bonne.

Dans l'exemple que vous avez posté, les deux boîtes sont équivalentes, de sorte que la méthode Equals renvoie la valeur true. Dans ce cas, le dictionnaire a deux Clés identiques, de sorte qu'il déclenche une exception.

TLDR

Donc en résumé, la méthode GetHashCode est utilisé pour générer une adresse où l'objet est stocké. Ainsi, un dictionnaire ne pas avoir à le rechercher. Il calcule le hashcode et les sauts à cet emplacement. La méthode Equals est un meilleur test de l'égalité, mais ne peut pas être utilisé pour mapper un objet dans un espace d'adressage.

Espère que ça aide

9voto

Ash Points 678

GetHashCode est utilisé dans Dictionnaire colections et il crée de hachage pour stocker des objets. Voici un joli article pourquoi et comment utiliser IEqualtyComparer et GetHashCode http://dotnetperls.com/iequalitycomparer

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