Dieser Artikel wurde maschinell übersetzt. Wenn Sie die englische Version des Artikels anzeigen möchten, aktivieren Sie das Kontrollkästchen Englisch. Sie können den englischen Text auch in einem Popupfenster anzeigen, indem Sie den Mauszeiger über den Text bewegen.
Übersetzung
Englisch

Object.GetHashCode-Methode: ()

 

Veröffentlicht: Oktober 2016

Fungiert als die Standardhashfunktion.

Namespace:   System
Assembly:  mscorlib (in mscorlib.dll)

public virtual int GetHashCode()

Rückgabewert

Type: System.Int32

Ein Hashcode für das aktuelle Objekt.

Ein Hashcode ist, einen numerischen Wert, der verwendet wird, einfügen, und identifizieren ein Objekt in einer Auflistung hashbasierten wie z. B. die Dictionary<TKey, TValue> -Klasse, die Hashtable Klasse oder abgeleitet der DictionaryBase Klasse. Die GetHashCode -Methode dieser Hashcode für die Algorithmen, die schnell überprüft der Objektgleichheit bereit.

System_CAPS_noteHinweis

Informationen zur Verwendung von Hashcodes in Hashtabellen und einige zusätzliche Code Hashalgorithmen, finden Sie unter der Hash Function Eintrag in Wikipedia.

Zwei Objekte, die gleich sind, geben denselben Hashcode zurück. Das Gegenteil gilt jedoch nicht: gleich Hashcodes implizieren keine Objektgleichheit, da verschiedene (ungleich) Objekte identische Hashcodes verfügen können. .NET Framework gewährleistet außerdem nicht die Standardimplementierung von der GetHashCode -Methode, und der Wert, der diese Methode gibt unterscheiden zwischen .NET Framework-Versionen und Plattformen wie 32-Bit- und 64-Bit-Plattformen. Aus diesen Gründen verwenden Sie nicht die standardmäßige Implementierung dieser Methode als eine eindeutige Objekt-ID für hashing Zwecke. Führen Sie die zwei folgen aus diesem:

  • Sie sollten nicht davon ausgehen, dass gleich Hashcodes Objektgleichheit implizieren.

  • Sie sollten nie beibehalten oder einen Hashcode außerhalb der Anwendungsdomäne, in der es erstellt wurde, verwenden, da das gleiche Objekt über Anwendungsdomänen, Prozessen und Plattformen hash kann.

System_CAPS_warningWarnung

Ein Hash ist für effizientes Einfügen und Suchen in den Auflistungen vorgesehen, die auf einer Hashtabelle basieren. Ein Hashcode ist kein permanente Wert. Aus diesem Grund:

  • Serialisieren Sie weder hashcodierte Darstellungen noch speichern Sie sie in den Datenbanken.

  • Verwenden Sie nicht den Hash als Schlüssel zum Abrufen eines Objekts aus einer schlüsselgebundenen Auflistung.

  • Senden Sie Hashcodes nicht anwendungsdomänen- oder prozessübergreifend. In einigen Fällen möglicherweise Hashcodes pro Domäne pro Prozess oder pro Anwendung berechnet werden.

  • Verwenden Sie nicht den Hashcode statt eines Werts von einer kryptografischen Hashfunktion zurückgegeben, wenn Sie einen kryptographisch starken Hash benötigen. Für kryptografische Hashes verwenden eine abgeleitete Klasse die System.Security.Cryptography.HashAlgorithm oder System.Security.Cryptography.KeyedHashAlgorithm Klasse.

  • Testen Sie nicht auf Gleichheit Hashcodes zu bestimmen, ob zwei Objekte gleich sind. (Ungleich Objekte können identische Hashcodes haben.) Um auf Gleichheit zu testen, rufen Sie die ReferenceEquals oder Equals Methode.

Die GetHashCode Methode kann von einem abgeleiteten Typ überschrieben werden. Wenn GetHashCode wird nicht überschrieben, Hashcodes für Verweistypen berechnete Spalten werden durch Aufrufen der Object.GetHashCode -Methode der Basisklasse, die einen Hashcode berechnet basierend auf ein Objekt Verweis; Weitere Informationen, finden Sie unter RuntimeHelpers.GetHashCode. Das heißt, zwei Objekte für die die ReferenceEquals -Methode gibt true haben identische Hashcodes. Wenn Werttypen nicht überschreiben GetHashCode, wird die ValueType.GetHashCode -Methode der Basisklasse verwendet Reflektion, um den Hashcode anhand der Werte der Felder des Typs berechnen. Anders gesagt haben Werttypen, deren Felder gleiche Werte haben, gleich Hashcodes. Weitere Informationen zum Außerkraftsetzen der GetHashCode, finden Sie im Abschnitt "Hinweise zur Vererbung".

System_CAPS_warningWarnung

Wenn Sie überschreiben die GetHashCode -Methode, Sie sollten auch überschreiben, Equals, und umgekehrt. Wenn die überschriebene Equals -Methode gibt true Wenn werden zwei Objekte hinsichtlich ihrer Gleichheit die überschriebene getestet GetHashCode Methode muss den gleichen Wert für die beiden Objekte zurückgeben.

Wenn ein Objekt, das als Schlüssel für Hashtabellen verwendet wird, keine geeignete Implementierung von bietet GetHashCode, können Sie einen Hashcode-Standardanbieter festlegen, indem eine IEqualityComparer -Implementierung, die eine Überladung von der Hashtable Klassenkonstruktor.

Beim Aufrufen der GetHashCode Methode einer Klasse in der Windows-Runtime, es ist das Standardverhalten für Klassen, die nicht außer Kraft setzen GetHashCode. Dies ist Teil der Unterstützung von .NET Framework für die Windows-Runtime (siehe .NET Framework-Unterstützung für Windows Store-Apps und Windows-Runtime). Klassen in der Windows-Runtime erben nicht Object, und zurzeit nicht implementiert eine GetHashCode. Allerdings haben sie scheinbar ToString, Equals(Object), und GetHashCode Methoden, wenn Sie diese C#- oder Visual Basic-Code verwenden, und .NET Framework das Standardverhalten für diese Methoden ist.

System_CAPS_noteHinweis

Windows-Runtime in c# oder Visual Basic geschrieben sind Klassen können überschreiben die GetHashCode Methode.

Hinweise für Vererber:

Eine Hashfunktion wird zum schnellen Generieren einer Zahl (Hashcode) verwendet, die dem Wert eines Objekts entspricht. Hashfunktionen müssen werden in der Regel spezifisch für jeden Typ und, um Eindeutigkeit herzustellen, mindestens eines der Instanzfelder als Eingabe. Mit den Werten der statische Felder sollten nicht Hashcodes berechnet werden.

Für Klassen abgeleitete Object, wird die GetHashCode -Methode der Basisklasse delegieren kann Object.GetHashCode() Implementierung nur, wenn die abgeleitete Klasse Gleichheit als Verweisgleichheit definiert. Die standardmäßige Implementierung des GetHashCode zu Referenzzwecken Typen gibt einen Hashcode, der von zurückgegeben entspricht der RuntimeHelpers.GetHashCode(Object) Methode. Sie können außer Kraft setzen GetHashCode für unveränderliche Verweistypen. Im Allgemeinen für änderbare Referenztypen, Sie sollten eine Überschreibung GetHashCode nur dann, wenn:

  • Sie den Hashcode aus Feldern ableiten können, die nicht geändert werden; oder

  • Sie können sicherstellen, dass der Hashcode eines änderbaren Objekts nicht ändert, während das Objekt in einer Auflistung enthalten ist, der den Hashcode verwendet.

Andernfalls könnte das änderbare Objekt möglicherweise in der Hashtabelle verloren gehen. Wenn Sie sich entscheiden, überschreiben GetHashCode einen änderbaren Referenztyp, der Dokumentation sollten, es klar, dass Benutzer des Typs Objektwerte nicht ändern sollten, während das Objekt in einer Hashtabelle gespeichert ist.

Bei Werttypen ValueType.GetHashCode Hash Code stellt eine Standardimplementierung bereit, die Reflektion verwendet. Sie sollten für eine bessere Leistung außer Kraft setzen.

System_CAPS_noteHinweis

Weitere Informationen und Beispiele, die Hashcodes auf verschiedenste Art und Weise berechnen, finden Sie im Beispielabschnitt.

Eine Hashfunktion muss die folgenden Eigenschaften aufweisen:

  • Wenn zwei Objekte als gleich, vergleichen die GetHashCode Methode für jedes Objekt muss den gleichen Wert zurückgeben. Jedoch, wenn die beiden Objekte nicht gleich, Vergleich der GetHashCode Methoden für die beiden Objekte müssen nicht unterschiedliche Werte zurückgeben.

  • Die GetHashCode -Methode eines Objekts muss immer zurückgeben, denselben Hashcode solange keine Änderung des Objektzustands, die den Rückgabewert, der des Objekts bestimmt Equals Methode. Beachten Sie, dass dies gilt nur für die aktuelle Ausführung einer Anwendung und ein anderen Hashcode zurückgegeben werden kann, wenn die Anwendung erneut ausgeführt wird.

  • Für optimale Leistung soll eine Hashfunktion eine gleichmäßige Verteilung für alle Eingaben generieren, einschließlich stark gruppierter Eingabe. Eine Folge ist, dass kleine Änderungen Objektstatus große Änderungen an den resultierenden Hashcode für eine optimale Leistung der Hash-Tabelle führen soll.

  • Hashfunktionen sollte günstig zu berechnen.

  • Die GetHashCode -Methode sollte keine Ausnahmen auslösen.

Zum Beispiel die Implementierung von der GetHashCode Methode von der String -Klasse gibt identische Hashcodes für identische Zeichenfolgenwerte zurück. Daher geben zwei String Objekte den gleichen Hashcode zurückgeben, wenn sie denselben Zeichenfolgenwert darstellen. Die Methode verwendet außerdem alle Zeichen in der Zeichenfolge verhältnismäßig zufällig verteilte Ausgabe zu generieren, auch wenn die Eingabe auf bestimmte Zeichenbereiche beschränkt ist (z. B. viele Benutzer möglicherweise Zeichenfolgen, die nur die unteren 128 ASCII-Zeichen enthalten, obwohl eine Zeichenfolge jedes der 65.535 Unicode-Zeichen enthalten kann).

Bereitstellen einer guten Hashfunktion für eine Klasse kann die Leistung Einfügen dieser Objekte in eine Hashtabelle erheblich beeinträchtigen. In einer Hashtabelle mit Schlüsseln, die eine gute Implementierung einer Hashfunktion bereitzustellen, hat sucht nach einem Element Konstanten Zeit (z. B. eine o(1)-Operation) aus. In einer Hashtabelle mit einer schlecht implementierten Hashfunktion, die Leistung einer Suche hängt die Anzahl der Elemente in der Hashtabelle (z. B. eine O (n)-Operation, wobei n ist die Anzahl der Elemente in der Hashtabelle). Böswilliger Benutzer kann Daten eingeben, die die Anzahl der Konflikte, erhöht die deutlich die Leistung der Anwendung beeinträchtigt werden kann, die abhängig von Hashtabellen unter folgenden Umständen:

  • Wenn Hashfunktionen häufig Konflikte erzeugen.

  • Wenn ein Großteil der Objekte in einer Hashtabelle Hashcodes, die gleich sind oder ungefähr gleich einander zu erzeugen.

  • Wenn Benutzer die Eingabe der Daten aus denen berechnete Hashcode.

Abgeleitete Klassen, die außer Kraft setzen GetHashCode müssen auch überschreiben Equals zu garantieren, dass zwei Objekte, die als gleich betrachtet, denselben Hashcode besitzen, andernfalls der Hashtable Typ möglicherweise nicht ordnungsgemäß.

Eine der einfachsten Methoden, um einen Hashcode für einen numerischen Wert zu berechnen, die identisch oder einen kleineren Bereich als das Int32 ist einfach, der Wert zurückgegeben. Das folgende Beispiel zeigt eine solche Implementierung für eine Number Struktur.

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

In vielen Fällen verfügt ein Typ mehrere Datenfelder, die beim Generieren des Hashcodes teilnehmen kann. Eine Möglichkeit, einen Hashcode zu generieren, kombinieren diese Felder mithilfe von ist ein XOR (eXclusive OR) Vorgang, wie im folgenden Beispiel gezeigt.

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

Das vorherige Beispiel gibt möglicherweise denselben Hashcode für n1, (n2) und (n2, n1) zurück und generiert damit mehr Konflikte, als erwünscht sind. Eine Reihe von Lösungen sind verfügbar, sodass nicht Hashcodes in diesen Fällen identisch sind. Den Hashcode des zurück ein Tuple -Objekt, das die Reihenfolge der jedes Feld entspricht. Das folgende Beispiel zeigt eine mögliche Implementierung, die Tuple<T1, T2> Klasse. Beachten Sie jedoch, den Overhead für die Instanziierung einer Tuple Objekt kann die allgemeine Leistung einer Anwendung, die große Anzahl von Objekten in Hashtabellen speichert erheblich beeinträchtigen.

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

Eine zweite alternative Lösung umfasst die Gewichtung der einzelnen Hashcodes von links-Verschiebung die Hashcodes aufeinander folgende Felder durch zwei oder mehr Bits. Optimal, anstatt Sie zu verwerfen, Bits über Bit 31 hinaus verschoben umschließen soll statt verworfen werden. Da von der Left Shift-Operatoren in c# und Visual Basic Bits verworfen werden, erfordert dies eine linke UMSCHALT-Wrap-Methode wie folgt erstellen:

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);
}

Das folgende Beispiel verwendet dann diese UMSCHALT-Wrap-Methode den Hashcode berechnet die Point Struktur, die in den vorherigen Beispielen verwendet.

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 

Universelle Windows-Plattform
Verfügbar seit 8
.NET Framework
Verfügbar seit 1.1
Portierbare Klassenbibliothek
Unterstützt in: portierbare .NET-Plattformen
Silverlight
Verfügbar seit 2.0
Windows Phone Silverlight
Verfügbar seit 7.0
Windows Phone
Verfügbar seit 8.1
Zurück zum Anfang
Anzeigen: