Was ist beim Überschreiben von Object.GetHashCode () in Klassen ohne unveränderliche Felder zurückzugeben?

Okay, bevor Sie wütend werden, weil im Internet Hunderte ähnlich klingender Fragen veröffentlicht werden, kann ich Ihnen versichern, dass ich gerade die letzten Stunden mit Lesen verbracht habealle von ihnen und habe die antwort auf meine frage nicht gefunden.

Hintergrund:

Grundsätzlich litt eine meiner Großanwendungen unter einer Situation, in der einige davon betroffen warenBindings auf derListBox.SelectedItem Die Eigenschaft funktioniert nicht mehr oder das Programm stürzt ab, nachdem das aktuell ausgewählte Element bearbeitet wurde. Ich habe anfangs die gefragt'Ein Element mit demselben Schlüssel wurde bereits hinzugefügt' Ausnahme beim Auswählen eines ListBoxItem aus dem Code Frage hier, bekam aber keine Antworten.

Ich hatte keine Zeit gehabt, dieses Problem anzusprechen, bis ich in dieser Woche einige Tage Zeit hatte, es zu klären. Um es kurz zu machen, ich habe den Grund für das Problem herausgefunden. Das lag daran, dass meine Datentypklassen die überschrieben hattenEquals Methode und damit dieGetHashCode Methode auch.

Für diejenigen unter Ihnen, die sich dieses Problems nicht bewusst sind, stellte ich fest, dass Sie nur das implementieren könnenGetHashCode Methode mitunveränderlich Felder / Eigenschaften. Mit einem Auszug aus Harvey Kwoks Antwort auf dieÜberschreiben von GetHashCode () poste, um dies zu erklären:

Das Problem ist, dass GetHashCode von Dictionary- und HashSet-Auflistungen verwendet wird, um jedes Element in einem Bucket zu platzieren. Wenn der Hashcode basierend auf einigen veränderlichen Feldern berechnet wird und die Felder wirklich geändert werden, nachdem das Objekt in das HashSet oder Dictionary gestellt wurde, kann das Objekt nicht mehr im HashSet oder Dictionary gefunden werden.

Also dietatsächlich Das Problem wurde verursacht, weil ich verwendet hatteveränderlich Eigenschaften in derGetHashCode Methoden. Wenn Benutzer diese Eigenschaftswerte in der Benutzeroberfläche änderten, änderten sich die zugehörigen Hash-Codewerte der Objekte, und dann wurden keine Elemente mehr in ihren Sammlungen gefunden.

Frage:

Meine Frage ist also, wie ich am besten mit der Situation umgehen kann, in der ich das implementieren mussGetHashCode Methode in Klassen ohne unveränderliche Felder? Entschuldigung, lassen Sie mich genauer sein, alsDas Fragehat wurde schon einmal gefragt.

Die Antworten in derÜberschreiben von GetHashCode () post schlägt vor, dass es in diesen Situationen besser ist, einfach einen konstanten Wert zurückzugeben ... einige schlagen vor, den Wert zurückzugeben1, während andere die Rückgabe einer Primzahl vorschlagen. Persönlich kann ich keinen Unterschied zwischen diesen Vorschlägen feststellen, da ich gedacht hätte, dass nur ein Eimer für einen von beiden verwendet wird.

Darüber hinaus ist dieRichtlinien und Regeln für GetHashCode Artikel in Eric Lipperts Blog hat einen Abschnitt mit dem TitelRichtlinie: Die Verteilung der Hash-Codes muss "zufällig" sein Dies hebt die Fallstricke der Verwendung eines Algorithmus hervor, der dazu führt, dass nicht genügend Eimer verwendet werden. Er warnt vor Algorithmen, dieVerringern Sie die Anzahl der verwendeten Eimer und verursachen Sie Leistungsprobleme, wenn der Eimer sehr groß wird. Das Zurückgeben einer Konstante fällt sicherlich in diese Kategorie.

Ich hatte die Idee, ein Extra hinzuzufügenGuid Feld auf alle meine Datentypklassen (nur in C #, nicht in der Datenbank), die speziell in und nur in derGetHashCode Methode. Also nehme ich am Ende dieses langen Intro an, meinetatsächlich Die Frage ist, welche Implementierung besser ist. Zusammenfassen:

Zusammenfassung:

Wenn Sie Object.GetHashCode () in Klassen ohne unveränderliche Felder überschreiben, ist es besser, eine Konstante von der zurückzugebenGetHashCode Methode, oder um eine zusätzliche zu erstellenreadonly Feld für jede Klasse, das ausschließlich in der Klasse verwendet werden sollGetHashCode Methode? Wenn ich ein neues Feld hinzufügen sollte, welcher Typ sollte es sein und sollte ich es dann nicht in das Feld einfügen?Equals Methode?

Ich freue mich über Antworten von allen, hoffe aber sehr auf Antworten von fortgeschrittenen Entwicklern mit soliden Kenntnissen zu diesem Thema.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage