Exporter (0) Imprimer
Développer tout
Cet article a fait l'objet d'une traduction automatique. Déplacez votre pointeur sur les phrases de l'article pour voir la version originale de ce texte. Informations supplémentaires.
Traduction
Source

Object.GetHashCode, méthode

Sert 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 en cours.

Un code de hachage est une valeur numérique utilisée pour insérer et identifier un objet dans une collection dictionnaires basée telle que la classe Dictionary<TKey, TValue>, la classe Hashtable, ou un type dérivé de la classe DictionaryBase. La méthode GetHashCode fournit ce code de hachage pour les algorithmes qui nécessitent des contrôles rapides de l'égalité d'objet.

RemarqueRemarque

Pour plus d'informations sur la façon dont les codes de hachage sont utilisés dans des tables de hachage et pour certains algorithmes supplémentaires de code de hachage, consultez l'entrée dans Wikipedia Fonction de hachage.

Deux objets qui sont égaux retournent des codes de hachage égaux. Toutefois, l'inverse n'est pas respectée : des codes de hachage égaux n'impliquent pas l'égalité d'objet, car des objets différent (non égaux) peuvent avoir des codes de hachage identiques. De plus, le .NET Framework ne garantit pas l'implémentation par défaut de la méthode GetHashCode, et la valeur de retour de cette méthode peut différer entre les versions du. Net Framework et les plateformes, telles que les plateformes 32 bits et 64 bits. Pour cela, n'utilisez pas l'implémentation par défaut de cette méthode en tant qu'identificateur d'objet unique à des fins de hachage. Deux conséquences découlent de ceci :

  • Vous ne devez pas supposer que des codes de hachage égaux impliquent l'égalité d'objet.

  • Vous ne devez jamais persister ou utiliser un code de hachage en dehors du domaine d'application dans lequel il a été créé, car le même objet peut hacher entre des domaines, les processus, et les plateformes d'application.

Mise en gardeAttention

Un code de hachage est prévu pour l'insertion efficace et la recherche dans les collections basées sur une table de hachage. Un code de hachage n'est pas une valeur définitive. C'est pourquoi :

  • Ne sérialisez pas les valeurs de code de hachage ou ne les enregistrez pas dans les bases de données.

  • N'utilisez pas le code de hachage comme clé pour récupérer un objet d'une collection comportant des clés.

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

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

  • Ne testez pas l'égalité des codes de hachage pour déterminer si deux objets sont égaux. (Des objets différents peuvent avoir des codes de hachage identiques.) Pour tester l'égalité, appelez ReferenceEquals ou la méthode Equals.

La méthode GetHashCode peut être substituée par un type dérivé. Si GetHashCode n'est pas substitué, les codes de hachage pour les types référence sont calculés en appelant la méthode Object.GetHashCode de la classe de base, qui calcule le code de hachage selon la référence d'un objet ; pour plus d'informations, consultez RuntimeHelpers.GetHashCode. En d'autres termes, deux objets pour lesquels la méthode retourne trueReferenceEquals ont des codes de hachage identiques. Si les types valeur ne remplacent pas GetHashCode, la méthode ValueType.GetHashCode de la classe de base utilise la réflexion pour calculer le code de hachage selon les valeurs des champs du type. En d'autres termes, les types valeur dont les champs ont des valeurs égales ont des codes de hachage égaux. Pour plus d'informations sur la substitution GetHashCode, consultez la section « Remarques pour les héritiers ».

Mise en gardeAttention

Si vous substituez la méthode GetHashCode, vous devez également substituer Equals, et inversement. Si votre méthode Equals substituée retourne true lorsque l'égalité de deux objets est testée, votre méthode GetHashCode substituée doit retourner la même valeur pour les deux objets.

Si un objet 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 une implémentation IEqualityComparer à l'une des surcharges de constructeur de classe Hashtable.

Remarques pour Windows Runtime

Lorsque vous appelez la méthode GetHashCode sur une classe dans Windows Runtime, elle fournit le comportement par défaut pour les classes qui ne substituent pas GetHashCode. Ceci fait partie du support que le Framework .NET fournit pour Windows Runtime (voir Prise en charge .NET Framework pour les applications Windows Store et Windows Runtime). Les classes de Windows Runtime n'héritent pas de Object, et n'appliquent pas de méthode GetHashCode. Toutefois, elles semblent avoir ToString, Equals(Object), et les méthodes GetHashCode lorsque vous les utilisez dans votre code C# ou Visual Basic, et .NET Framework fournissent le comportement par défaut pour ces méthodes.

RemarqueRemarque

Les classes Windows Runtime écrites en C# ou en Visual Basic peuvent substituer la méthode GetHashCode.

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. Les fonctions de hachage sont généralement propres à chaque type et, pour des questions d'unicité, doivent utiliser au moins un des champs de l'instance comme entrée. Les codes de hachage ne doivent pas être calculés en utilisant les valeurs des champs statiques.

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

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

  • Vous pouvez garantir que le code de hachage d'un objet mutable ne change pas pendant que l'objet est contenu dans une collection basée sur son code de hachage.

Sinon, vous pourriez penser que l'objet mutable est perdu dans la table de hachage. Si vous choisissez de substituer GetHashCode pour un type référence mutable, votre documentation doit expliquer que les utilisateurs de votre type ne doivent pas modifier les valeurs d'objet pendant que 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 la substituer pour de meilleures performances.

RemarqueRemarque

Pour plus d'informations et d'exemples qui calculent les codes de hachage de diverses manières, consultez la section Exemples.

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

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

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

  • Pour optimiser les performances, une fonction de hachage doit générer une répartition égale pour toute entrée, et ce même pour une entrée qui est fortement groupée. Une conséquence est que les petites modifications apportées à l'état d'objet doivent entraîner de grands changements au code de hachage résultant pour de meilleures performances de la table de hachage.

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

  • La méthode GetHashCode ne doit pas lever d'exceptions.

Par exemple, l'implémentation de la méthode GetHashCode fournie par la classe String retourne des codes de hachage identiques pour des valeurs de chaîne identiques. Par conséquent, deux objets String 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 de 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 n'importe lesquels des 65 535 caractères Unicode).

Si vous fournissez une fonction de hachage adéquate sur une classe, cela peut affecter considérablement les performances lors de l'ajout de ces objets à une table de hachage. Dans une table de hachage avec des clés qui offrent une bonne implémentation d'une fonction de hachage, la recherche d'un élément prend une durée constante (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 dépendent du nombre d'éléments contenus dans la table de hachage (par exemple, une opération O(n), où n correspond au nombre d'éléments figurant dans la table de hachage). Un utilisateur malveillant peut entrer des données qui augmentent le nombre de collisions, ce qui peut considérablement diminuer les performances des applications qui dépendent des tables de hachage, dans les conditions suivantes :

  • Lorsque les fonctions de hachage produisent des collisions fréquentes.

  • Lorsqu'une grande proportion d'objets dans une table de hachage produit des codes de hachage égaux ou quasiment égaux entre eux.

  • Lorsque les utilisateurs entrent les données depuis lesquelles le code de hachage est calculé.

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

L'une des méthodes les plus simples pour calculer un code de hachage pour une valeur numérique qui a la même portée ou une portée plus petite que le type Int32 est de retourner simplement cette valeur. L'exemple suivant illustre une telle implémentation pour la structure Number.


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


Il arrive fréquemment qu'un type possède plusieurs champs de données qui peuvent participer à la génération du code de hachage. Une manière de générer un code de hachage consiste à combiner ces champs à l'aide d'une opération XOR (eXclusive OR), comme le montre 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), etc. et peut ainsi générer plus de collisions que ce qui est souhaitable. De nombreuses solutions sont disponibles afin que les codes de hachage dans ces cas ne soient pas identiques. L'une de ces solutions est de retourner un code de hachage d'un objet Tuple qui correspond à l'ordre de chaque champ. L'exemple suivant illustre une implémentation possible qui se sert de la classe Tuple<T1, T2>. Notez, pourtant, que la baisse du plafond des performances d'instancier un objet Tuple peut considérablement affecter les performances générales d'une application qui enregistre un grand nombre d'objets dans des 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 deuxième solution alternative implique de peser les codes de hachage individuels en décalant vers la gauche les codes de hachage de champs consécutifs de deux bits ou plus. De façon optimale, au lieu d'être ignoré, les bits déplacés au delà de bits 31 doivent revenir au début plutôt que d'être ignorés. Comme des bits sont ignorés par les opérateurs de décalage vers la gauche en C# comme en Visual Basic, il faut créer une méthode de décalage à gauche et de retour au début comme indiqué par la suite :


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 de décalage et de retour pour calculer le code de hachage de la structure Point 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 


.NET Framework

Pris en charge dans : 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Pris en charge dans : 4, 3.5 SP1

Bibliothèque de classes portable

Pris en charge dans : Bibliothèque de classes portable

.NET pour les applications du Windows Store

Pris en charge dans : Windows 8

.NET pour les applications Windows Phone

Pris en charge dans : Windows Phone 8, Silverlight 8.1

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (rôle principal du serveur non pris en charge), Windows Server 2008 R2 (rôle principal du serveur pris en charge avec SP1 ou version ultérieure ; Itanium non pris en charge)

Le .NET Framework ne prend pas en charge toutes les versions de chaque plateforme. Pour obtenir la liste des versions prises en charge, consultez Configuration requise du .NET Framework.

Ajouts de la communauté

AJOUTER
Afficher:
© 2014 Microsoft