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 ein numerischer Wert, der verwendet wird, zum Einfügen und identifizieren z. B. ein Objekt in einer Auflistung hashbasierten der Dictionary<TKey, TValue> -Klasse, die Hashtable Klasse oder einen Typ abgeleitet wurde. die DictionaryBase Klasse. Die GetHashCode Methode bietet diese Hashcode für Algorithmen, die schnelle Überprüfung der Objektgleichheit benötigen.

System_CAPS_noteHinweis

Informationen zur Verwendung von Hashcodes in Hashtabellen sowie 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 stimmt aber nicht "true": gleich Hashcodes implizieren keine Objektgleichheit, da verschiedene (ungleich) Objekte identische Hashcodes verfügen können. .NET Framework gewährleistet zudem nicht die standardmäßige Implementierung des der GetHashCode -Methode, und der Wert, der diese Methode gibt unterschiedlich ausfallen, zwischen .NET Framework-Versionen und Plattformen, wie z. B. 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 Konsequenzen aus diesem:

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

  • Sie sollten nie beibehalten oder einen Hashcode außerhalb der Anwendungsdomäne, in der es erstellt wurde, verwenden, da das gleiche Objekt zwischen 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 an, um ein Objekt aus einer schlüsselgebundenen Auflistung abzurufen.

  • Senden Sie Hashcodes nicht anwendungsdomänen- oder prozessübergreifend. In einigen Fällen können der 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 kryptografisch starken Hash benötigen. Verwenden Sie für kryptografische Hashes eine abgeleitete Klasse die System.Security.Cryptography.HashAlgorithm oder System.Security.Cryptography.KeyedHashAlgorithm Klasse.

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

Die GetHashCode Methode kann durch einen abgeleiteten Typ überschrieben werden. Wenn GetHashCode ist nicht außer Kraft gesetzt, Hashcodes für Verweistypen berechnet 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 auf dem die ReferenceEquals -Methode zurückkehrt true haben identische Hashcodes. Wenn Werttypen nicht außer Kraft setzen GetHashCodedie ValueType.GetHashCode -Methode der Basisklasse verwendet Reflektion, um den Hashcode anhand der Werte der Felder des Typs zu berechnen. Werttypen, deren Felder identische Werte haben, haben also gleich Hashcodes. Weitere Informationen zum Überschreiben GetHashCode, finden Sie im Abschnitt "Hinweise zur Vererbung".

System_CAPS_warningWarnung

Wenn Sie überschreiben die GetHashCode , Sie sollten auch-methodenüberschreibung Equals, und umgekehrt. Wenn die überschriebene Equals -Methode zurückkehrt true Wenn werden zwei Objekte auf Gleichheit, die außer Kraft gesetzte getestet GetHashCode Methode muss für die beiden Objekte den gleichen Wert zurück.

Wenn ein Objekt, das in einer Hashtabelle als Schlüssel verwendet wird, keine geeignete Implementierung von bietet GetHashCode, Sie können einen Hashcode-Standardanbieter angeben, durch Angabe einer IEqualityComparer -Implementierung, die eine der Überladungen der der Hashtable Klassenkonstruktor.

Beim Aufrufen der GetHashCode Methode einer Klasse in der Windows-Runtime, es stellt 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 implementieren eine GetHashCode. Allerdings sie angezeigt werden, damit ToString, Equals(Object), und GetHashCode Methoden, wenn Sie in c# oder Visual Basic-Code werden verwendet, und die .NET Framework das Standardverhalten für diese Methoden bietet.

System_CAPS_noteHinweis

Windows-RuntimeKlassen, die in c# oder Visual Basic geschrieben sind, können außer Kraft setzen die GetHashCode Methode.

Hinweise für Vererber:

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

Für Klassen abgeleitete Object, GetHashCode -Methode der Basisklasse delegieren kann Object.GetHashCode() Implementierung nur, wenn die abgeleitete Klasse Gleichheit als Verweisgleichheit definiert. Die standardmäßige Implementierung des GetHashCode Referenzzwecken Typen zurückgibt einen Hashcode, der zurückgegeben wird, indem Sie 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, wenn:

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

  • Sie können sicherstellen, dass der Hashcode des ein änderbares Objekt nicht ändert, während das Objekt in einer Auflistung enthalten ist, die abhängig von dessen Hashcode.

Andernfalls könnte das änderbare Objekt möglicherweise in der Hashtabelle verloren gehen. Wenn Sie sich entschließen, überschreiben GetHashCode für einen änderbaren Referenztyp Ihrer Dokumentation sollte unbedingt verdeutlicht werden, dass Benutzer Ihres 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. Erwägen Sie, ob Sie es für eine bessere Leistung zu überschreiben.

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ück. Jedoch, wenn die beiden Objekte nicht gleich, Vergleich der GetHashCode Methoden für die beiden Objekte müssen keine unterschiedliche Werte zurückgeben.

  • Die GetHashCode Methode für ein Objekt muss immer zurückgeben, denselben Hashcode, solange es ist keine Änderung an der Zustand des Objekts, das den Rückgabewert, der des Objekts bestimmt Equals Methode. Beachten Sie, dass dies nur während der aktuellen Ausführung einer Anwendung "true" ist 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 kleinere Änderungen an den Objektzustand in umfangreichen Änderungen an den resultierenden Hashcode für eine optimale Leistung der Hash-Tabelle führen soll.

  • Hashfunktionen sollten kostengünstigen berechnet werden.

  • Die GetHashCode Methode sollte keine Ausnahmen auslösen.

Z. B. die Implementierung von der GetHashCode Methode bereitgestellt wird, indem Sie die String Klasse gibt identische Hashcodes für identische Zeichenfolgenwerte zurück. Aus diesem Grund zwei String Objekte den gleichen Hashcode zurückgeben, wenn diese 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 in bestimmten Bereichen gruppiert ist (z. B. viele Benutzer möglicherweise Zeichenfolgen, die nur die unteren 128 ASCII-Zeichen enthalten, obwohl eine Zeichenfolge, die die 65.535 Unicode-Zeichen enthalten kann).

Bietet eine gute Hashfunktion für eine Klasse kann die Leistung dieser Objekte hinzugefügt. eine Hashtabelle spürbar verringern. In einer Hashtabelle mit Schlüsseln, die eine gute Implementierung einer Hashfunktion bereitstellen, wird die Suche nach einem Element Konstanten Zeit (z. B. eine o(1)-Operation). In einer Hashtabelle durch eine schlechte Implementierung einer Hashfunktion, die Leistung einer Suche hängt die Anzahl der Elemente in der Hashtabelle (z. B. eine O (n) Vorgang, wobei n ist die Anzahl der Elemente in der Hashtabelle). Ein böswilliger Benutzer kann Daten einzugeben, die die Anzahl der Konflikte, vergrößert die deutlich die Leistung der Anwendung beeinträchtigen können, die abhängig von Hashtabellen in den folgenden Situationen:

  • Wenn Hashfunktionen häufig Konflikte erzeugen.

  • Wenn eine große Menge von Objekten in einer Hashtabelle Hashcodes, die gleich sind oder ungefähr gleich untereinander erzeugen.

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

Abgeleitete Klassen, die außer Kraft setzen GetHashCode müssen auch überschreiben Equals um sicherzustellen, dass zwei Objekte als gleich betrachtet, denselben Hashcode haben, andernfalls die Hashtable Typ funktionieren eventuell nicht richtig.

Einer der einfachsten Möglichkeiten, einen Hashcode für einen numerischen Wert zu berechnen, der der gleichen oder einer kleineren Bereich als hat die Int32 ist einfach, der Wert zurückgegeben. Das folgende Beispiel zeigt eine 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 hat einen Typ mehrere Datenfelder, die beim Generieren des Hashcodes einbezogen werden können. 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 Hashcodes in diesen Fällen nicht identisch sind. Eine besteht darin, den Hashcode des Zurückgeben einer Tuple -Objekt, das die Reihenfolge der jedes Feld entspricht. Das folgende Beispiel zeigt eine mögliche Implementierung, verwendet die Tuple<T1, T2> Klasse. Beachten Sie jedoch, die die Beeinträchtigung der Systemleistung der Instanziierung einer Tuple Objekt kann erhebliche Auswirkungen auf die allgemeine Leistung einer Anwendung, in der großen Anzahl von Objekten in Hashtabellen gespeichert.

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 der Hashcodes von aufeinander folgenden Feldern von zwei oder mehr Bits. Optimal, anstatt verworfen werden, Bits verschoben hinter Bit 31 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);
}

Im 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: