Your GetHashCode
method only depends on y
. That means if your Equals
method doesn't depend on y
, you've broken the contract of equality... they're inconsistent.
Distinct()
is going to expect that equal elements have the same hash code. In your case, the only equal elements by x
value have different hash codes, therefore Equals
won't even get called.
From the docs of IEquatable<T>.Equals
:
If you implement
Equals
, you should also override the base class implementations ofObject.Equals(Object)
andGetHashCode
so that their behavior is consistent with that of theIEquatable<T>.Equals
method.
Your implementation of Equals(Foo)
isn't consistent with either Equals(object)
or GetHashCode
.
EqualityComparer<T>.Default
will still delegate to your GetHashCode
method - it will just use your Equals(T)
method in preference to your Equals(object)
method.
So to answer your questions in order:
- Why does the independent implementation of
IEquatable<T>
corrupt the equality comparison?
Because you've introduced an inconsistent implementation. It's not meant to be independent in terms of behaviour. It's just meant to be more efficient by avoiding a type check (and boxing, for value types).
- Can it play a role independent of the
Equals
andGetHashCode
overrides?
It should be consistent with Equals(object)
for the sake of sanity, and it must be consistent with GetHashCode
for the sake of correctness.
If not, why does
EqualityComparer<T>.Default
look for this implementation first?
To avoid runtime type checking and boxing/unboxing, primarily.