Skip to content

Enumerable.Distinct requires the GetHashCode override to work on default comparer #3572

Open
@AgentMC

Description

@AgentMC

The docs say (https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.distinct?view=netframework-4.8#System_Linq_Enumerable_Distinct__1_System_Collections_Generic_IEnumerable___0__)

If you want to return distinct elements from sequences of objects of some custom data type, you have to implement the IEquatable<T> generic interface in the class. The following code example shows how to implement this interface in a custom data type and provide GetHashCode and Equals methods.

This is confusing and wrong. IEquatable<T> interface only (!) requires to implement the bool Equals(T other); method. However, inside Distinct() (and probably other similar methods such as group by, etc) also compares the hash codes of the object, which it takes from the EqualityComparer<T>.Default, which, while being created for an implementation of IEquatable<T>, that does not have the override for GetHashCode(T object), uses the default T.GetHashCode().

Consequence: if I follow the "must" part of the doc and implement ONLY IEquatable<T> interface, that method (bool Equals(T other);) even isn't being called! Which naturally totally confuses me as for what did I do wrong.

How to fix: TBH I'd say the implementation here with IEquatable<T> itself is very questionable. It should've been IEqualityComparer. But for the docs, please at least add the note that "If you want to return distinct elements from sequences of objects of some custom data type, you have to implement the IEquatable<T> generic interface in the class AND override the inherited GetHashCode() method. For consistency, after that you should also override the inherited Equals() method. ..."

Metadata

Metadata

Assignees

No one assigned

    Labels

    Pri3Indicates issues/PRs that are low priorityarea-System.Linqhelp wantedGood for community contributors to help [up-for-grabs]

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions