Cet article a fait l’objet d’une traduction automatique. Pour afficher l’article en anglais, activez la case d’option Anglais. Vous pouvez également afficher le texte anglais dans une fenêtre contextuelle en faisant glisser le pointeur de la souris sur le texte traduit.
Traduction
Anglais

Object.GetHashCode méthode ()

 

Date de publication : novembre 2016

Fait office de fonction de hachage par défaut.

Espace de noms:   System
Assembly:  mscorlib (dans mscorlib.dll)

public virtual int GetHashCode()

Valeur de retour

Type: System.Int32

Code de hachage pour l'objet actuel.

Un code de hachage est une valeur numérique qui est utilisée pour insérer et identifier un objet dans une collection basée sur le hachage comme le Dictionary<TKey, TValue> (classe), la Hashtable classe ou un type dérivé de la DictionaryBase classe. Le GetHashCode méthode fournit ce code de hachage pour les algorithmes qui ont besoin de vérifications rapides de l’égalité d’objet.

System_CAPS_noteRemarque

Pour plus d’informations sur l’utilisation des codes de hachage dans les tables de hachage et pour certains algorithmes de code de hachage supplémentaires, consultez le Hash Function entrée dans Wikipedia.

Deux objets qui sont égaux retournent des codes de hachage égaux. Toutefois, l’inverse n’est pas vrai : les codes de hachage égales n’impliquent pas l’égalité d’objet, car différents objets (inégaux) peuvent avoir des codes de hachage identiques. En outre, le .NET Framework ne garantit pas l’implémentation par défaut de la GetHashCode méthode et la valeur de cette méthode est retournée peut varier entre les versions du .NET Framework et de plateformes, telles que les plateformes 32 bits et 64 bits. Pour ces raisons, n’utilisez pas l’implémentation par défaut de cette méthode comme un identificateur d’objet pour des raisons de hachage. Deux conséquences suivent à partir de ce :

  • Vous ne devez pas supposer que les codes de hachage égale impliquent l’égalité d’objet.

  • Ne jamais conserver ou si vous utilisez un code de hachage en dehors du domaine d’application dans lequel il a été créé, car le même objet peuvent être hachées sur les plateformes, les processus et domaines d’application.

System_CAPS_warningAvertissement

Un code de hachage est destiné aux efficace d’insertion et de recherche dans les collections sont basées sur une table de hachage. Un code de hachage n’est pas une valeur permanente. Pour cette raison :

  • Ne pas sérialiser les valeurs de code de hachage ou les stocker dans les bases de données.

  • N’utilisez pas le code de hachage comme clé pour récupérer un objet à partir d’une collection à clé.

  • N’envoyez pas de codes de hachage entre les domaines d’application ou processus. Dans certains cas, les codes de hachage peuvent être calculées sur une base domaine par processus ou par application.

  • N’utilisez pas le code de hachage au lieu d’une valeur renvoyée par une fonction de hachage cryptographique, si vous avez besoin d’un hachage cryptographique efficace. Pour les hachages de chiffrement, utilisez une classe dérivée de la System.Security.Cryptography.HashAlgorithm ou System.Security.Cryptography.KeyedHashAlgorithm (classe).

  • Ne testez pas l’égalité des codes de hachage pour déterminer si deux objets sont égaux. (Les objets inégales peuvent avoir des codes de hachage identiques.) Pour tester l’égalité, appelez le ReferenceEquals ou Equals (méthode).

Le GetHashCode méthode peut être substituée par un type dérivé. Si GetHashCode est ne pas substituée, des codes de hachage pour les types référence sont calculées en appelant le Object.GetHashCode méthode de la classe de base qui calcule un code de hachage basé sur les références d’un objet ; pour plus d’informations, consultez RuntimeHelpers.GetHashCode. En d’autres termes, deux objets pour lesquels le ReferenceEquals méthode renvoie true ont des codes de hachage identiques. Si vous ne remplacent pas les types de valeur GetHashCode, la ValueType.GetHashCode méthode de la classe de base utilise la réflexion pour calculer le code de hachage basé sur les valeurs des champs du type. En d’autres termes, les types de valeur dont les champs ont des valeurs égales ont des codes de hachage égale. Pour plus d’informations sur la substitution de GetHashCode, consultez la section « Remarques à l’attention des héritiers ».

System_CAPS_warningAvertissement

Si vous substituez la GetHashCode (méthode), vous devez également substituer Equals, et vice versa. Si votre Equals méthode true lorsque les deux objets sont testées pour l’égalité, votre GetHashCode méthode doit retourner la même valeur pour les deux objets.

Si un objet qui est utilisé comme clé dans une table de hachage ne fournit pas une implémentation utile de GetHashCode, vous pouvez spécifier un fournisseur de code de hachage en fournissant un IEqualityComparer mise en œuvre à une des surcharges de la Hashtable constructeur de classe.

Lorsque vous appelez le GetHashCode méthode sur une classe dans le Windows Runtime, il fournit le comportement par défaut pour les classes qui ne remplacent pas GetHashCode. Ceci fait partie du support que le .NET Framework fournit pour Windows Runtime (voir Prise en charge .NET Framework pour les applications Windows Store et Windows Runtime). Classes de la Windows Runtime n’hérite pas de Object, et vous n’implémentez pas actuellement un GetHashCode. Toutefois, ils semblent avoir ToString, Equals(Object), et GetHashCode méthodes lorsque vous les utilisez dans votre code c# ou Visual Basic et le .NET Framework fournit le comportement par défaut pour ces méthodes.

System_CAPS_noteRemarque

Windows Runtime les classes qui sont écrits en c# ou Visual Basic peuvent remplacer les GetHashCode (méthode).

Remarques à l’attention des héritiers :

Une fonction de hachage est utilisée pour générer rapidement un nombre (code de hachage) qui correspond à la valeur d’un objet. Fonctions de hachage sont généralement propres à chaque type et, pour l’unicité, doivent utiliser au moins un des champs d’instance comme entrée. Codes de hachage ne doivent pas être calculées en utilisant les valeurs des champs statiques.

Pour les classes dérivées de Object, la GetHashCode méthode peut déléguer à la classe de base Object.GetHashCode() implémentation uniquement si la classe dérivée définit l’égalité comme l’égalité des références. L’implémentation par défaut de GetHashCode pour référence types retourne un code de hachage qui est équivalent à celui retourné par le RuntimeHelpers.GetHashCode(Object) (méthode). Vous pouvez substituer GetHashCode pour les types référence immuable. En règle générale, pour les types référence mutables, vous devez substituer GetHashCode uniquement si :

  • Vous pouvez calculer le code de hachage à partir de champs qui ne sont pas mutables ; ou

  • Vous pouvez vous assurer que le code de hachage d’un objet mutable ne change pas pendant que l’objet est contenu dans une collection qui s’appuie sur son code de hachage.

Sinon, vous pourriez penser que l’objet mutable est perdue au cours de la table de hachage. Si vous choisissez de remplacer GetHashCode pour un type référence mutable, votre documentation doit indiquer clairement que les utilisateurs de votre type ne devraient pas modifier les valeurs d’objet lorsque l’objet est stocké dans une table de hachage.

Pour les types valeur, ValueType.GetHashCode fournit une implémentation de code de hachage par défaut qui utilise la réflexion. Vous devez envisager de substitution pour de meilleures performances.

System_CAPS_noteRemarque

Pour plus d’informations et des exemples de codes de hachage de plusieurs façons de calcul, consultez la section Exemples.

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

  • Si deux objets sont considérés comme égaux, la GetHashCode méthode pour chaque objet doit retourner la même valeur. Toutefois, si deux objets ne sont pas considérés comme égaux, la GetHashCode méthodes pour les deux objets ne doivent pas retourner des valeurs différentes.

  • Le GetHashCode méthode pour un objet doit constamment retourner le même code de hachage tant qu’il n’existe aucune modification de l’état de l’objet qui détermine la valeur de retour de l’objet Equals (méthode). Notez que cela est vrai uniquement pour l’exécution d’une application en cours, et qu’un code de hachage différent peut être retourné si l’application est exécutée à nouveau.

  • Pour des performances optimales, une fonction de hachage doit générer une distribution uniforme pour toutes les entrées, y compris les entrées qui sont fortement en cluster. Une conséquence est que les petites modifications à l’état de l’objet doivent aboutir à grand modifications dans le code de hachage qui en résulte pour de meilleures performances de table de hachage.

  • Fonctions de hachage doivent être peu coûteuses à calculer.

  • Le GetHashCode méthode lever d’exceptions.

Par exemple, l’implémentation de la GetHashCode méthode fournie par la String classe renvoie les codes de hachage identiques pour les valeurs de chaîne identiques. Par conséquent, deux String objets retournent 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 dans la chaîne pour générer une sortie distribuée de manière raisonnablement aléatoire, même si l’entrée est ordonnée en clusters dans certaines plages (par exemple, de nombreux utilisateurs peuvent posséder des chaînes contenant uniquement les 128 caractères ASCII inférieurs, même si une chaîne peut contenir les 65 535 caractères Unicode).

En fournissant une fonction de hachage adéquate sur une classe peut affecter considérablement les performances de l’ajout de ces objets à une table de hachage. Dans une table de hachage avec des clés qui fournissent une implémentation correcte de la fonction de hachage, la recherche d’un élément du temps constant (par exemple, une opération o (1)). Dans une table de hachage possédant une mauvaise implémentation d’une fonction de hachage, les performances d’une recherche varie selon le nombre d’éléments dans la table de hachage (par exemple, un O (n) opération, où n est le nombre d’éléments dans la table de hachage). Un utilisateur malveillant peut entrer des données qui augmente le nombre de collisions, ce qui peut dégrader considérablement les performances des applications qui dépendent de tables de hachage, les conditions suivantes :

  • Lorsque les fonctions de hachage produisent des conflits fréquents.

  • Lorsqu’une grande quantité d’objets dans une table de hachage produisent des codes de hachage qui sont égaux ou approximativement égal à l’autre.

  • Lorsque les utilisateurs d’entrée les données à partir de laquelle le code de hachage est calculé.

Classes dérivées qui substituent GetHashCode doit également substituer Equals pour garantir que deux objets considérés comme égaux possèdent le même code de hachage ; sinon, le Hashtable type peuvent ne pas fonctionne correctement.

Une des méthodes plus simples pour calculer un code de hachage pour une valeur numérique qui a la même ou à une plage plus petite que la Int32 est de type à retourner simplement cette valeur. L’exemple suivant montre une telle implémentation pour un Number structure.

using System;

public struct Number
{
   private int n;

   public Number(int value)
   {
      n = value;
   }

   public int Value
   {
      get { return n; }
   }

   public override bool Equals(Object obj)
   {
      if (obj == null || ! (obj is Number)) 
         return false;
      else
         return n == ((Number) obj).n;
   }      

   public override int GetHashCode()
   {
      return n;
   }

   public override string ToString()
   {
      return n.ToString();
   }
}

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      for (int ctr = 0; ctr <= 9; ctr++) {
         int randomN = rnd.Next(Int32.MinValue, Int32.MaxValue);
         Number n = new Number(randomN);
         Console.WriteLine("n = {0,12}, hash code = {1,12}", n, n.GetHashCode());
      }   
   }
}
// The example displays output like the following:
//       n =   -634398368, hash code =   -634398368
//       n =   2136747730, hash code =   2136747730
//       n =  -1973417279, hash code =  -1973417279
//       n =   1101478715, hash code =   1101478715
//       n =   2078057429, hash code =   2078057429
//       n =   -334489950, hash code =   -334489950
//       n =    -68958230, hash code =    -68958230
//       n =   -379951485, hash code =   -379951485
//       n =    -31553685, hash code =    -31553685
//       n =   2105429592, hash code =   2105429592

Souvent, un type présente plusieurs champs de données qui peuvent participer à la génération du code de hachage. Permet de générer un code de hachage consiste à combiner ces champs à l’aide un XOR (eXclusive OR) opération, comme indiqué dans l’exemple suivant.

using System;

// A type that represents a 2-D point.
public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (! (obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return x ^ y;
    } 
} 

public class Example
{
   public static void Main()
   {
      Point pt = new Point(5, 8);
      Console.WriteLine(pt.GetHashCode());

      pt = new Point(8, 5);
      Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       13
//       13

L’exemple précédent retourne le même code de hachage pour (n1, n2) et (n2, n1) et par conséquent, peut générer des collisions plus que souhaitable. Plusieurs solutions sont disponibles afin que les codes de hachage dans ces cas ne sont pas identiques. Une est pour renvoyer le code de hachage d’un Tuple objet qui reflète l’ordre de chaque champ. L’exemple suivant montre une implémentation possible qui utilise le Tuple<T1, T2> classe. Notez, cependant, que la surcharge des performances de l’instanciation d’un Tuple objet peut affecter considérablement les performances globales d’une application qui stocke un grand nombre d’objets dans les tables de hachage.

using System;

public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (!(obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return Tuple.Create(x, y).GetHashCode();
    } 
} 

public class Example
{
   public static void Main()
   {
        Point pt = new Point(5, 8);
        Console.WriteLine(pt.GetHashCode());

        pt = new Point(8, 5);
        Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       173
//       269

Une autre solution de remplacement implique les codes de hachage individuels de pondération en utilisant les codes de hachage de champs successifs à gauche par deux ou plusieurs bits. Idéalement, au lieu d’être ignorés, bits décalés au-delà de bit 31 doivent habiller plutôt qu’ignorées. Étant donné que les bits sont ignorés par les opérateurs de décalage vers la gauche en c# et Visual Basic, cela requiert la création d’une méthode MAJ-wrap gauche comme suit :

public int ShiftAndWrap(int value, int positions)
{
    positions = positions & 0x1F;

    // Save the existing bit pattern, but interpret it as an unsigned integer.
    uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
    // Preserve the bits to be discarded.
    uint wrapped = number >> (32 - positions);
    // Shift and wrap the discarded bits.
    return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
}

L’exemple suivant utilise ensuite cette méthode MAJ-wrap pour calculer le code de hachage de la Point structure utilisée dans les exemples précédents.

using System;

public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (!(obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return ShiftAndWrap(x.GetHashCode(), 2) ^ y.GetHashCode();
    } 

    private int ShiftAndWrap(int value, int positions)
    {
        positions = positions & 0x1F;

        // Save the existing bit pattern, but interpret it as an unsigned integer.
        uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
        // Preserve the bits to be discarded.
        uint wrapped = number >> (32 - positions);
        // Shift and wrap the discarded bits.
        return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
    }
} 

public class Example
{
   public static void Main()
   {
        Point pt = new Point(5, 8);
        Console.WriteLine(pt.GetHashCode());

        pt = new Point(8, 5);
        Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       28
//       37 

Plateforme Windows universelle
Disponible depuis 8
.NET Framework
Disponible depuis 1.1
Bibliothèque de classes portable
Pris en charge dans : plateformes .NET portables
Silverlight
Disponible depuis 2.0
Silverlight pour Windows Phone
Disponible depuis 7.0
Windows Phone
Disponible depuis 8.1
Retour au début
Afficher: