(0) exportieren Drucken
Alle erweitern
Dieser Artikel wurde maschinell übersetzt. Bewegen Sie den Mauszeiger über die Sätze im Artikel, um den Originaltext anzuzeigen. Weitere Informationen
Übersetzung
Original

Object.GetHashCode-Methode

Fungiert als die Standardhashfunktion.

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

public virtual int GetHashCode()

Rückgabewert

Typ: System.Int32
Ein Hashcode für das aktuelle Objekt.

Ein Hash ist ein numerischer Wert, der verwendet wird, um ein Objekt in einer hashbasierten Auflistung wie der Dictionary<TKey, TValue>-Klasse, der Hashtable-Klasse oder einem Typ einzufügen und zu bestimmen, der von der DictionaryBase-Klasse abgeleitet ist. Die GetHashCode-Methode stellt diesen Hashcode für Algorithmen bereit, die die schnelle Überprüfungen der Objektgleichheit benötigen.

HinweisHinweis

Informationen darüber, wie das in den Hashtabellen und einige zusätzliche Hashcodealgorithmen verwendet werden, finden Sie den Hashfunktion Eintrag im Wikipedia.

Zwei Objekte, die gleich sind, geben denselben Hashcode zurück. Allerdings trifft der Umkehrschluss nicht zu: gleiche Hashcodes bedeuten nicht Objektgleichheit, da verschiedene (ungleiche) Objekte über identische Hashcodes verfügen können. Weiterhin garantiert das .NET Framework keine Standardimplementierung der Methode GetHashCode. Der Wert den diese Methode zurückgibt, kann sich zwischen .NET Framework-Versionen und Plattformen (wie 32-Bit- und 64-Bit-Plattformen) unterscheiden. Aus diesen Gründen sollten Sie die Standardimplementierung dieser Methode nicht als eindeutige Objekt-ID beim Hashing verwenden. Daraus folgt:

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

  • Sie sollten einen Hashcode außerhalb der Anwendungsdomäne nicht beibehalten oder verwenden, in der es erstellt wurde, da das gleiche Objekt möglicherweise über Anwendungsdomänen, Prozessen und wendet Plattformen.

WarnhinweisVorsicht

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

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

  • Verwenden Sie den Hash nicht als Schlüssel, um ein Objekt von einer schlüsselgebundenen Auflistung abzurufen.

  • Senden Sie Hashcodes nicht anwendungsdomänen- oder prozessübergreifend. In einigen Fällen werden Hashcodes per Prozess oder per Anwendungsdomäne berechnet.

  • Verwenden Sie den Hash nicht anstelle eines Werts, der durch eine kryptografische Hashverfahrensfunktion zurückgegeben wird, wenn Sie einen kryptografischen starken Hash benötigen. Für kryptografische Hashs verwenden Sie eine Klasse, die von der System.Security.Cryptography.HashAlgorithm oder System.Security.Cryptography.KeyedHashAlgorithm-Klasse abgeleitet ist.

  • Testen Sie nicht auf Gleichheit von Hashcodes um zu ermitteln, ob zwei Objekte gleich sind.(Ungleiche Objekte können identische Hashcodes haben.) Für eine Überprüfung auf Gleichheit, rufen Sie die Methode ReferenceEquals oder Equals auf.

Die GetHashCode-Methode kann von einem abgeleiteten Typ überschrieben werden. Wenn GetHashCode nicht überschrieben wird, werden Hashcodes für Referenztypen berechnet, indem die Object.GetHashCode-Methode der Basisklasse aufgerufen wird, die einen Hashcode entsprechend dem Verweis eines Objekts berechnet; Weitere Informationen finden Sie unter RuntimeHelpers.GetHashCode. Das heißt zwei Objekte, für die die ReferenceEquals-Methode true zurückgibt, haben identische Hashcodes. Wenn Werttypen GetHashCode nicht überschreiben, nutzt die ValueType.GetHashCode-Methode der Basisklasse Reflektion, um den Hashcode anhand der Werte der Felder des Typs zu berechnen. Das heißt Werttypen mit identischen Werten der Felder haben dieselben Hashcodes. Weitere Informationen zum Überschreiben von GetHashCode, finden Sie im Abschnitt "Hinweise zur Vererbung".

WarnhinweisVorsicht

Wenn Sie die GetHashCode-Methode überschreiben, sollten Sie außerdem Equals überschreiben und umgekehrt. Wenn Ihre überschriebene Equals-Methode true zurückgibt, wenn zwei Objekte auf Gleichheit getestet werden, muss die GetHashCode-Methode den gleichen Wert für die zwei Objekte zurückgeben.

Wenn ein Objekt, das verwendet wird, wie ein Schlüssel in einer Hashtabelle keine nützliche Implementierung von GetHashCode bereitstellt, Sie einen Hashcodeanbieter angeben kann, indem eine IEqualityComparer Implementierung auf eine der Überladungen des Hashtable-Klassenkonstruktors angeben.

Hinweise für Windows-Runtime

Wenn Sie die GetHashCode-Methode für eine Klasse in Windows-Runtime aufrufen, definiert dies das Standardverhalten für Klassen, die GetHashCode nicht überschreiben. Dies ist Teil der Unterstützung, die .NET Framework für Windows-Runtime bietet (siehe .NET Framework-Unterstützung für Windows Store-Apps und Windows-Runtime). Klassen in Windows-Runtime erben nicht von Object und implementieren momentan nicht GetHashCode. Diese Klassen werden jedoch ToString, Equals(Object) und GetHashCode-Methoden aufweisen, wenn Sie diese in ihrem C#- oder Visual Basic-Code verwenden, und das .NET Framework wird das Standardverhalten für diese Methoden bereitstellen.

HinweisHinweis

Windows-Runtime-Klassen, die in C# oder Visual Basic geschrieben werden, können die GetHashCode-Methode überschreiben.

Hinweise zur Vererbung

Eine Hashfunktion wird zum schnellen Generieren einer Zahl (Hashcode) verwendet, die dem Wert eines Objekts entspricht. Hashfunktionen sind normalerweise für jeden Typ spezifisch und müssen, um Eindeutigkeit zu gewährleisten, mindestens eines der Instanzfelder als Eingabe verwenden . Hashcodes sollten nicht berechnet werden, indem man die Werte von statischen Feldern verwendet.

Bei den Klassen, die von Object abgeleitet werden, kann die GetHashCode-Methode zu Basisklassen Object.GetHashCode() die Implementierung bei, nur die abgeleitete Klasse Gleichheit definiert, um Verweisgleichheit zu sein. Die Standardimplementierung von GetHashCode für Referenztypen gibt einem Hashcode zurück, der von den entspricht, der durch die RuntimeHelpers.GetHashCode(Object)-Methode zurückgegeben wird. Sie können GetHashCode für unveränderliche Referenztypen überschreiben. Im Allgemeinen für änderbare Verweistypen, sollten Sie GetHashCode überschreiben, wenn:

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

  • Sie sicherstellen können, dass sich der Hashcode eines änderbaren Objekts nicht ändert während das Objekt in einer Auflistung enthalten ist, die auf einem Hashcode beruht.

Andernfalls könnte das änderbare Objekt möglicherweise in der Hashtabelle verloren gehen. Wenn Sie festlegen, dass GetHashCode für einen änderbaren Referenztyp zu überschreiben, sollte die Dokumentation deutlich erhöhen, dass Benutzer des Typs Objektwerte nicht ändern sollten, während das Objekt in einer Hashtabelle gespeichert wird.

Für Werttypen stellt ValueType.GetHashCode eine Standardhashcodeimplementierung, die Reflektion verwenden. Sie sollten es, eine bessere Leistung zu überschreiben können.

HinweisHinweis

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

Eine Hashfunktion muss folgende Eigenschaften aufweisen:

  • Wenn ein Vergleich zweier Objekte deren Gleichheit ergibt, müssen die GetHashCode-Methoden beider Objekte den gleichen Wert zurückgeben. Wenn jedoch zwei Objekte miteinander vergleichen nicht als gleich, müssen die GetHashCode-Methoden für die beiden Objekte verschiedene Werte nicht zurückgeben.

  • Die GetHashCode-Methode eines Objekts muss immer denselben Hashcode zurückgeben, solange keine Änderung des Objektzustands erfolgt, die den Rückgabewert der Equals-Methode des Objekts beeinflusst. Beachten Sie, dass diese Anforderungen lediglich für die aktuelle Ausführung einer Anwendung gelten und dass bei der nächsten Ausführung ein anderer Hashcode zurückgegeben werden kann.

  • Für optimale Leistung soll eine Hashfunktion eine gleichmäßige Verteilung für alle Eingaben generieren, einschließlich stark gruppierter Eingabe. Eine Auswirkungen ist, dass kleine Änderungen am Objektzustand umfangreiche Änderungen dem resultierenden Hashcode für optimale Hashtabellenleistung ergeben sollten.

  • Hashfunktionen sollten ressourcenschonend zu berechnen sein.

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

Die Implementierung der GetHashCode-Methode in der String-Klasse gibt z. B. für identische Zeichenfolgenwerte identische Hashcodes zurück. Daher geben zwei String-Objekte denselben Hashcode zurück, wenn sie denselben Zeichenfolgenwert darstellen. Darüber hinaus verwendet die Methode sämtliche Zeichen der Zeichenfolge, um eine verhältnismäßig zufällig verteilte Ausgabe zu erzielen, auch wenn die Eingabe auf bestimmte Zeichenbereiche beschränkt ist (z. B. wenn viele Benutzer nur Zeichenfolgen verwenden, die die unteren 128 ASCII-Zeichen enthalten, obwohl eine Zeichenfolge jedes der 65.535 Unicode-Zeichen enthalten könnte).

Das Bereitstellen einer effizienten Hashfunktion für eine Klasse kann das Einfügen dieser Objekte in eine Hashtabelle erheblich beschleunigen. In einer Hashtabelle mit Schlüsseln, die eine sinnvolle Implementierung einer Hashfunktion bereitstellt, benötigt die Suche nach einem Element eine konstante Zeit(beispielsweise eine O(1) Operation.) Bei einer Hashtabelle mit einer schlecht implementierten Hashfunktion hängt die Dauer der Suche von der Anzahl der Elemente in der Tabelle ab (sie ist z. B. eine O( n)-Operation, wobei n die Anzahl der Elemente in der Hashtabelle bezeichnet). Ein böswilliger Benutzer kann Eingabedaten, die die Anzahl von Konflikten auf, mit denen die Leistung von Anwendungen erheblich beeinträchtigen können, die den von Hashtabellen abhängig sind, unter den folgenden Bedingungen:

  • Wenn Hashfunktionen häufige Konflikte erzeugen.

  • Wenn eine große Menge der Objekte einer Hashtabelle Hashcodes erzeugt die annähernd gleich sind oder miteinander übereinstimmen.

  • Wenn Benutzer Daten eingegeben haben, von denen der Hashcode abgeleitet wird.

Abgeleitete Klassen, die GetHashCode überschreiben, müssen außerdem Equals überschreiben, damit gewährleistet ist, dass zwei Objekte, die als gleich betrachtet werden, denselben Hashcode besitzen. Andernfalls könnte der Hashtable-Typ falsche Ergebnisse liefern.

Eine der einfachsten Methoden, einen Hash für einen numerischen Wert, der gleich oder hat einen kleineren Bereich als Typ Int32 abgeleitet werden soll, diesem Wert einfach zurückzugeben. Im folgenden Beispiel wird eine solche Number Implementierung für eine 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


Häufig besitzt ein Typ mehrere Datenfelder, die zur Generierung des Hashcodes beitragen können. Eine Möglichkeit, einen Hashcode zu generieren, ist diese Felder mithilfe eines XOR (eXclusive OR) Operation, wie im folgenden Beispiel dargestellt zu kombinieren.


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 stehen zur Verfügung, sodass die Hashcodes in diesen Fällen nicht identisch sind. Eine ist, den Hashcode eines Tuple-Objekts zurückzugeben, welches die Reihenfolge der einzelnen Felder reflektiert. Im folgenden Beispiel wird eine mögliche Implementierung an, die die Tuple<T1, T2>-Klasse verwendet. Hinweis, obwohl, dem der Verwaltungsaufwand durch Instanziieren eines Tuple-Objekts einer Anwendung wesentlich die Gesamtleistung auswirkt, die viele Objekte im Hashtabellen speichert.


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, scrollen die einzelnen von Hashcodes Belasseneverschiebung die Hashcode aus aufeinander folgenden Feldern von zwei oder mehr Bits zu gewichten. Optimal anstelle verworfen werden, Bits verschoben wurde zu 31 Bit hinaus, Umbruch sondern verworfen werden sollte. Wenn Bits von den Linksschiebeoperatoren in C# und Visual Basic verworfen werden, erfordert dieses das Erstellen einer linken UMSCHALTTASTE-undUmbruchsmethode wie dem folgenden:


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 folgenden Beispiel verwendet dann diese UMSCHALTTASTE-undUmbruchsmethode, um den Hashcode der Struktur Point zu berechnen, die in den vorherigen Beispielen verwendet wird.


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

Unterstützt in: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Unterstützt in: 4, 3.5 SP1

Portable Klassenbibliothek

Unterstützt in: Portable Klassenbibliothek

.NET für Windows Store-Apps

Unterstützt in: Windows 8

.NET für Windows Phone-Apps

Unterstützt in: 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 (Server Core-Rolle wird nicht unterstützt), Windows Server 2008 R2 (Server Core-Rolle wird mit SP1 oder höher unterstützt; Itanium wird nicht unterstützt)

.NET Framework unterstützt nicht alle Versionen sämtlicher Plattformen. Eine Liste der unterstützten Versionen finden Sie unter Systemanforderungen für .NET Framework.

Community-Beiträge

HINZUFÜGEN
Anzeigen:
© 2014 Microsoft