Dictionaries and GetHashCode()

Yesterday I had a small problem while implementing a class that had a Dictionary<key, value> , where the key was a small class (containing a name and a version code).

I had implemented this override for Equals:

public override bool Equals(object obj)
{
if (obj is
Key)
{
if (this.name ==
((Key)obj).name &&
this.version ==
((Key)obj).version)
return true;
else
return false;
}
else
throw new
ArgumentException("Can only compare with Key objects")
;
}

But I left the GetHashCode with the default override:

public override int GetHashCode()
{
return base.GetHashCode()
;
}

I had unit tested the class isolated and everything was working fine.

Then, I used this class into another one, and my new unit tests for the new class started to fail when performing a Contains() call, having the same values for name and version...

After digging on MSDN, I found this:

"The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value it returns will be the same between different versions of the .NET Framework. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes."

In my situation, it was acting weird the opposite, generating different hash codes for Key objects with exactly the same values (but different memory positions).

So, I did a quick rewrite of the GetHashCode() method...

public override int GetHashCode()
{
return (name + version).GetHashCode()
;
}

And now it works perfectly. If Key's name and version are the same, the hash code will be the same and this calls will return true: myColl.Contains(new Key("myName", "1.0");

Lesson learned: If you are going to compare objects, remember to override GetHashCode().

Tags: Development

Dictionaries and GetHashCode() article, written by Kartones. Published on