2010-07-23 15 views
13

Hey alle, ich habe gelesen, auf die beste Weise, die GetHashCode() - Überschreibung für Objekte in .NET zu implementieren, und die meisten Antworten, die ich renne, beinhalten irgendwie Zahlen von Mitgliedern, die sind numerische Typen, um mit einer Methode zu kommen. Problem ist, habe ich ein Objekt, das eine alphanumerische Zeichenfolge als Schlüssel verwendet, und ich frage mich, ob etwas grundlegend falsch ist mit nur einer internen ID für Objekte mit Zeichenfolgen als Schlüssel, etwas wie folgt verwenden?GetHashCode() mit String-Schlüsseln


// Override GetHashCode() to return a permanent, unique identifier for 
// this object. 
static private int m_next_hash_id = 1; 
private int m_hash_code = 0; 
public override int GetHashCode() { 
    if (this.m_hash_code == 0) 
    this.m_hash_code = <type>.m_next_hash_id++; 
    return this.m_hash_code; 
} 

Gibt es eine bessere Art und Weise für ein Objekt mit einem eindeutigen Hash-Code zu entwickeln, die eine alphanumerische Zeichenfolge als Schlüssel verwendet? (Und nein, die numerischen Teile der alphanumerischen Zeichenfolge sind nicht eindeutig; einige dieser Zeichenfolgen enthalten überhaupt keine Zahlen.) Alle Gedanken wären willkommen!

Antwort

19

Sie können GetHashCode() mit den nicht numerischen Werten aufrufen, die Sie in Ihrem Objekt verwenden.

private string m_foo; 
public override int GetHashCode() 
{ 
    return m_foo.GetHashCode(); 
} 
+0

Aber was ist, wenn sich diese Zeichenfolge ändert? Zum Beispiel könnte ich ein neues Benutzerobjekt erstellen mit: Benutzer foo = new User(); und der Konstruktor setzt User.Id = "". Später, wenn ich User.Id = "A12345" sage; und ich gebe this.Id.GetHashCode() als das Ergebnis von foo.GetHashCode() zurück, hat es sich nicht geändert, verletzt das Prinzip, dass sich der Hash-Code eines Objekts nie ändern sollte? –

+6

Das Objekt wurde geändert. Der Hash-Code * muss sich ebenfalls ändern *. –

+0

@King - es gibt ein paar verschiedene Möglichkeiten, Hash-Codes zu verwenden. Der Wert des Hash-Codes muss bei gleichem Startwert immer gleich sein. Wenn Ihr Wert veränderbar ist, müssen Sie den resultierenden Hashcode speichern und ihn stattdessen zurückgeben, wenn 'GetHashCode()' aufgerufen wird. –

0

Ja, ein besserer Weg wäre, den Hashcode der Zeichenfolge zu verwenden, die Sie bereits haben. Wenn die alphanumerische Zeichenfolge die Identität des Objekts definiert, das Sie haben, ist der Hashcode für den Hashcode Ihres Objekts sehr gut geeignet.

Die Idee, ein statisches Feld zu erhöhen und es als Hashcode zu verwenden, ist schlecht. Der Hash-Code sollte eine gleichmäßige Verteilung über den Raum möglicher Werte haben. Dies stellt unter anderem sicher, dass es gut funktioniert, wenn es als Schlüssel in einer Hashtabelle verwendet wird.

0

Ich glaube, Sie in der Regel GetHashCode() etwas zurückgeben möchten, das das Objekt identifiziert, indem es Wert ist, anstatt es ist Beispiel, wenn ich die Idee, hier bin zu verstehen, ich glaube, Ihre Methode GetHashCode() auf zwei verschiedene Objekte mit äquivalenten Werten gewährleisten würde würde verschiedene Hashes zurückgeben, nur weil sie verschiedene Instanzen sind.

GetHashCode() soll einen Wert zurückgeben, mit dem Sie zwei Objektwerte vergleichen können, nicht ihre Referenzen.

2

Hash-Codes müssen nicht eindeutig sein. Vorausgesetzt, Ihre Equals Implementierung ist korrekt, ist es in Ordnung, den gleichen Hash-Code für zwei Instanzen zurückzugeben. Die m_next_hash_id Logik ist fehlerhaft, da zwei Objekte unterschiedliche Hash-Codes haben, selbst wenn sie gleich sind.

MSDN enthält eine Reihe von Anweisungen zur Implementierung von Equals und GetHashCode. Several of the examples here implementieren GetHashCode in Bezug auf die Hash-Codes eines Objekts Felder

18

Dies ist kein gutes Muster zum Erzeugen von Hashes für ein Objekt.

Es ist wichtig, den Zweck zu GetHashCode undunderstand() - es ist ein Weg, eine numerische Darstellung der identifizierenden Eigenschaften eines Objekts zu erzeugen. Hash-Codes werden verwendet, um zu ermöglichen, dass ein Objekt als Schlüssel in einem Wörterbuch dient, und beschleunigen in manchen Fällen Vergleiche zwischen komplexen Typen.

Wenn Sie einfach einen zufälligen Wert generieren und es einen Hash-Code nennen, haben Sie keine Wiederholbarkeit. Eine andere Instanz mit denselben Schlüsselfeldern hat einen anderen Hash-Code und verletzt das von Klassen wie HashSet, Dictionary usw. erwartete Verhalten.

Wenn Sie bereits ein identifizierendes String-Mitglied in Ihrem Objekt haben, geben Sie einfach seinen Hash-Code zurück .

Die documentation on MSDN for implementers of GetHashCode() ist eine für jedermann lesen muß, die auf Überschreiben dieser Methode Pläne:

Hinweise zur Implementierung

Eine Hashfunktion verwendet wird, um schnell eine Zahl zu erzeugen (hash Code), der dem Wert eines Objekts entspricht. Hash-Funktionen sind , die normalerweise für jeden Typ spezifisch sind, und für Eindeutigkeit müssen mindestens die Instanzfelder als Eingabe verwendet werden.

muss Eine Hash-Funktion, die folgende Eigenschaften haben:

Wenn zwei Objekte gleich, ist die GetHashCode Verfahren für jedes Objekt müssen den gleichen Wert zurück. Wenn jedoch zwei Objekte nicht gleich vergleichen, müssen die GetHashCode-Methoden für das Objekt zwei verschiedene Werte nicht zurückgeben.

GetHashCode Die Methode für ein Objekt müssen den gleichen Hash-Code konsequent zurück, solange es keine Änderung an dem Objekt fest, dass den Rückgabewert des Objekts bestimmt Methode des Gleichen. Beachten Sie, dass diese nur für die aktuelle Ausführung einer Anwendung gilt, und dass ein anderer Hash-Code zurückgegeben werden kann, wenn die Anwendung erneut ausgeführt wird.

Für die beste Leistung muss eine Hash-Funktion eine zufällige Verteilung für alle Eingabe generieren.

Zum Beispiel ist die Umsetzung des GetHashCode Verfahrens durch die String-Klasse gibt identische Hash-Codes für identische Zeichenfolgenwerte. Daher geben zwei String-Objekte denselben Hash-Code zurück, wenn sie den gleichen Zeichenfolgenwert darstellen. Auch die Methode, um alle Zeichen in der Zeichenfolge verwendet maßen zufällig verteilte Ausgabe zu erzeugen, auch wenn die Eingang in bestimmten Bereichen gruppiert ist (zum Beispiel könnten viele Benutzer haben Strings, die nur die untere 128 ASCII enthalten Zeichen, auch wenn ein String eines der 65.535 Unicode-Zeichen enthalten kann).

Verwandte Themen