I just had to add another answer because one of the more obvious (and easiest to implement) solutions were not mentioned - not including the collection in your GetHashCode
calculation!
The main thing that seemed to have forgotten here is that the uniqueness from the result of GetHashCode
isn't required (or in many cases even possible). Unequal objects don't have to return unequal hash codes, the only requirement is that equal objects return equal hash codes. So by that definition, the following implementation of GetHashCode
is correct for all objects (assuming there's a correct Equals
implementation):
public override int GetHashCode()
{
return 42;
}
Of course this would yield the worst possible performance in hashtable lookup, O(n) instead of O(1), but it is still functionally correct.
With that in mind, my general recommendation when implementing GetHashCode
for an object that happens to have any kind of collection as one or more of its members is to simply ignore them and calculate GetHashCode
solely based on the other scalar members. This would work pretty well except if you put into a hash table a huge number of objects where all their scalar members have identical values, resulting in identical hash codes.
Ignoring collection members when calculating the hash code can also yield a performance improvement, despite the decreased distribution of the hash code values. Remember that using a hash code is supposed to improve performance in a hash table by not requiring to call Equals
N times, and instead will only require calling GetHashCode once and a quick hash table lookup. If each object has an inner array with 10,000 items which all participate in the calculation of the hash code, any benefits gained by the good distribution would probably be lost. It would be better to have a marginally less distributed hash code if generating it is considerably less costly.