Have you ever faced an issue of having duplicated key objects in your Hashtable even though the objects represent the same entity? In this post I’ll show a way to circumvent the Hashtable behavior.
Sometimes we have a need to use objects as Hashtable keys instead of strings. At least for me, most of the time, Hashtables are used as standard dictionaries such as in the sample below:
The code above produces the following outcome:
In the sample above, the value of “key2” key has been updated as expected. Also notice that the Hash value of key2 is the same on both DisplayResults() executions.
Now, what happens if instead of using a string as the key, we use an object? Here’s the updated code after we change the key from string to a custom object:
And here’s the outcome:
As you can see by the resulting outcome above, when I tried to update the instance of User 123, the Hashtable actually added the object as a new item to the collection and updated its value instead.
Why does this happen? Actually, the results of the second test are the ones we should expect when working with Hashtables as each newly created object receives a new hashcode value, and the Hashtable uses the hashcode value to search for keys in the collection. So, when the new user was created to update the value of the existing one, the new hashcode value given to the new object was used to search for an existing item in the collection; and as it could not be found, the object was added as a new item in the collection.
But, why doesn’t this happen with strings? They’re also objects, correct? String objects have a different behavior as they override object class methods to always consider equal two strings holding the same values even if they are actually different instances. On the first code sample, Let’s change the statement that updates the value of key2 to the following:
After running the program, we’ll get the following results:
This result looks like the second test results when a custom object was used as the key; only at this time, we used a string. Why didn’t we get the same results as our first test? Notice that I have updated the “k” (lowercase) to “K” (uppercase) to make the values of each string object different. So, if you look at the resulting outcome, the “Key2” string has a different hashcode value than the “key2” one, what means that the overridden GetHashCode() string method didn’t come into play and the Hashtable behaved as it should.
Now that we have covered the basics, how do I make my custom object behave like the string object to prevent duplication of objects representing the same entity in my collection? Simple, we’ll have to update our User class to override two methods of the object class: GetHashCode() and Equals().
Here’s the new User class with the overridden methods:
In case you’re lost, we’re doing two things here: first, we’re overriding the GetHashCode() method to return the hashcode of the UserCode property value (a string) instead of the hascode of the User instance itself. This way, two User instances with the same UserCode value will have the same hashcode value. And second, we’re overriding the Equals() method to use the value of the UserCode property for comparison; this way the class can identify whether or not two instances of the User class represent the same entity.
Here is the outcome of our program after the two object methods have been overridden:
It’s nice isn’t it? Now we can easily update the value part of User keys in the collection without worrying that duplicated User keys will be added to the collection.