Should I implement non-generic GetHashCode and Equals if my class implements IEqualityComparer<T>?
Update:
My hope was that MS updated implementation of their collection when they introduced IEqualityComparer<T>. So I thought that Dictionary and any other collection classes will check internally if my class implements IEqualityComparer<T> and use not generic methods GetHashCode and Equals only if that interface is not implemented. Without collections support that interface has very little value.
Update2:
I just checked Dictionary.FindEntry(TKey key) using ILSpy. It uses IEqualityComparer<TKey> (varriable comparer below). In fact I did not find any using of not generic GetHashCode and Equals functions at all.
int num = this.comparer.GetHashCode(key) & 2147483647;
for (int i = this.buckets[num % this.buckets.Length]; i >= 0; i = this.entries[i].next)
{
if (this.entries[i].hashCode == num
&& this.comparer.Equals(this.entries[i].key, key))
{
return i;
}
}
So it seems to that my class only needs to implement IEqualityComparer<T> to be properly used with Dictionary.
I understand that there will be no harm to implement not generic functions just in case.
But should we spend time if it brings no value?
I will make my question more specific:
Should I implement non-generic GetHashCode and Equals if my class implements IEqualityComparer<T> and:
- I do not use not generic collections in my code
- Third party code does not call
GetHashCodeandEqualsmethods of my code.
Does Microsoft code still needs non generic versions to work properly?
Update3:
I think I got it. I thought that IEqualityComparer<T> is to be implemented inside my class. In that case we would have generic and not generic versions of methods in one place.
That is not how IEqualityComparer<T> should be used. It should be implemented as separate class and used as parameter.
Thanks to everybody.
IEqualityComparer is meant to replace the default implemenation of GetHashCode and Equals every .NET object already has. This interface is only used by Dictionaries and (Hash)Sets to use a different hashing and comparison scheme as the object by default uses.
If your object is used in Dictionaries and HashTables as key you should first to override Equals and GetHashCode to let the Sets/Dictionaries use the default comparer (the one you call EqualityComparere.Default) for your object which does call Equals and GetHashCode of your object anyway.
The only reason to provide an external comparer via IEqualityComparer is to use a different comparison scheme. E.g. for strings you can choose from the BCL StringComparer class between case sensitive and case insensitive variants.
Update1
The intention of this question was why List and other collections always use the default comparer and not the one provided by the object. If an object does implement Equals and GetHashCode already why should List not use them if the object does at the same time also implements IEqualityComparer? Since List does not provide a ctor which does allow to use a different comparer it does need to use the default one.
But if you want to use different ones you always can use LINQ which does fix this issue by allowing you to pass explicitely your own comparer for a specific metho. E.g. Enumerable.Contains has an overload where you can pass in your own comparer.
From MSDN Sample: