traf ich ein paar Plätze online, wo Code in etwa so aussah:Verwenden Sie F # 's Hash-Funktion in GetHashCode() böse?
[<CustomEquality;NoComparison>]
type Test =
| Foo
| Bar
override x.Equals y =
match y with
| :? Test as y' ->
match y' with
| Foo -> false
| Bar -> true // silly, I know, but not the question here
| _ -> failwith "error" // don't do this at home
override x.GetHashCode() = hash x
Aber wenn ich die oben in FSI ausführen, wird die Abfrage nicht zurück, wenn entweder ich hash foo
auf einer Instanz von Test
oder anrufen, wenn ich Rufen Sie foo.GetHashCode()
direkt an.
let foo = Test.Foo;;
hash foo;; // no returning to the console until Ctrl-break
foo.GetHashCode();; // no return
konnte ich nicht ohne weiteren Beweis, aber es legt nahe, dass hash x
Anrufe GetHashCode()
auf dem Objekt, das bedeutet, dass der obige Code gefährlich ist. Oder spielt nur FSI?
Ich dachte, Code wie oben bedeutet nur "bitte benutzerdefinierte Gleichheit implementieren, aber lassen Sie die Hash-Funktion als Standard".
Ich habe inzwischen dieses Muster anders implementiert, frage mich aber immer noch, ob ich richtigerweise davon ausgehe, dass hash
nur GetHashCode()
aufruft, was zu einer ewigen Schleife führt.
Als Nebenwirkung, kehrt sofort Gleichheit innerhalb FSI mit, was darauf hindeutet, dass es entweder nicht
Update: Dies ist sinnvoll, wie im obigen Beispiel GetHashCode()
vor dem Vergleich nicht nennen, oder es tut etwas anderes.
x.Equals
nicht GetHashCode()
aufrufen, und der Gleichheitsoperator ruft in Equals
, nicht in GetHashCode()
.
_ "wäre, wenn Sie einige Mitglieder eines Objekts manuell hashen" _, ja, dies begann tatsächlich mit dem Erstellen eines vergleichbaren Funktionstyps, ähnlich wie 'string * (' T -> 'U) ', wo in der Hash-Überschreibung Ich habe 'hash s' in der Zeichenfolge aufgerufen (also keine unendliche Rekursion dort). Aber als ich diese Threads online sah, dachte ich mir, hey, lass es uns ausprobieren ... Führe zu dieser Frage. – Abel
Danke für den Zeiger auf den Quellcode. Und über Ihren Kommentar zu der Ausnahme: Sie haben Recht, schlechter Beispielcode ... Ich habe herumalbern. – Abel
@Abel Ja, ich dachte, du wüsstest das wahrscheinlich, aber ich dachte es lohnt sich für andere Leute, die diese Frage/Antwort sehen, da es einer dieser üblichen kleinen Fehler ist, der ziemlich leicht zu machen ist. – TheInnerLight