Posts Tagged custom keys

Key’s Equality in Hashtables (or who equal to who?)

Consider the following simple class:

public class SomeClass
{
uint _id = 125;public SomeClass(uint id)
  {
  _id = id;
  }
public override int GetHashCode()
  {
return (int)_id;
  }
}

We want to add instance of this class to hashtable, where the key is object’s ID, and the value is object itself. If we doing the following, it works:

SomeClass someClass = new SomeClass(125);
//1.

//========
hashTable[someClass.GetHashCode()] = someClass;
object returnValue = hashTable[125];
 

The returnValue is exactly our someClass instance. However, using value types as keys as bad, due to boxing each time key is passed to the hashtable. How we can improve this? Well, as known, inside hashtable ‘GetHashCode’ method is being called to determine the key. Therefore we can pass as a key the object itself, and override the ‘GetHashCode’ method (which is exactly what we did). Let’s try this code:

//2.
//===========
hashTable[someClass] = someClass;
SomeClass key =
new SomeClass(125);
returnValue = hashTable[key];

If you will run this code, you will see the returnValue is null. So what is wrong? When you trying to retrieve your object from hashtable and passing the key, hashtable using ‘Equals’ method, to find the right key. By default, after confirming the hashcode is the same, it comparing references, so in the code above the result is false. Obvious, the solution is to override the ‘Equals’ method (here is the one possible solution):

public override bool Equals(object obj)
{
return (_id == obj.GetHashCode());
}

If we run this code, that works ok. Now, we want to retrieve the object by passing the ID directly, without creating wrapper around it (as I said before, this is bad because of boxing – don’t do that in production code):

hashTable[someClass] = someClass;
returnValue = hashTable[125];

We overrided the Equals method, so this will work? No, it will not. You see, the hashtable comparing the passed key to the stored keys, and not storing keys to passed one. As a result, the ‘Equals’ method is invoked on the passed key – in our example it’s an integer – and it never equal to SomeClass, ofc. The conlcusion is: if you using your custom classes as hashtable keys, always override ‘GetHashCode’ and ‘Equals’ methods. And remember to use only your classes for the lookup inside the hashtable.

2 comments January 15, 2008


Categories

Top Posts

Tags

.NET addin app.config ArrayList bug CAB Configuration ConfigurationManager ConfigurationSection ContentControl ContextMenu CTime; DateTime custom keys DataBinding DataContext Data templates debugging equals gethashcode GUI Hashtable interlocked Invoke lock lock free memcpy MFC multithreading multithreading; lock free override performance SCSF serialization Smart Client Software Factory Styles System.Configuration unsafe virtual functions Visual Studio wait free WinAPI WinForms WinForms\WPF Integration World of Warcraft World of Warcraft; Addon

Archives