I encountered a couple of places online where code looked something like this:
[<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
But when I run the above in FSI, the prompt does not return when I either call hash foo
on an instance of Test
or when I call foo.GetHashCode()
directly.
let foo = Test.Foo;;
hash foo;; // no returning to the console until Ctrl-break
foo.GetHashCode();; // no return
I couldn't readily proof it, but it suggests that hash x
calls GetHashCode()
on the object, which means the above code is dangerous. Or is it just FSI playing up?
I thought code like the above just means "please implement custom equality, but leave the hash function as default".
I have meanwhile implemented this pattern differently, but am still wondering whether I am correct in assuming that hash
just calls GetHashCode()
, leading to an eternal loop.
As an aside, using equality inside FSI returns immediately, suggesting that it either does not call Update: this makes sense as in the example above GetHashCode()
prior to comparison, or it does something else.x.Equals
does not call GetHashCode()
, and the equality operator calls into Equals
, not into GetHashCode()
.