Migrating from Hashtable to Dictionary<K,V> - beware of a difference in the indexer behavior

| No Comments | No TrackBacks

I'm migrating lots of code to the .NET 2.0 nowadays and wanted to warn my readers about one particularly nasty migration issue. When moving from Hashtable to Dictionary<K, V> look carefully at the indexer usage - there is a runtime breaking change here. With Hashtable when you do myhashtable[mykey] and myhashtable doesn't contain mykey you just get null. But Dictionary<K, V> in this case throws KeyNotFoundException! This is of course not due to the evil will of Microsoft, but because unlike Hashtable, Dictionary<K, V> can store not only reference but value types too, so null is not an option anymore. Read a discussion at Brad Abrams's blog for more info about how this shit happened.

When working with Hashtable it's quite natural to write code like this:

Foo f = (Foo)myhashtable[mykey];
if (f != null) 
{
  //work with f
}
When moving to Dictionary<K, V> this code would compile but will throw KeyNotFoundException whenver mykey isn't in myhashtable. You gotta change this code.

There are two options here. First - every time you need to get a value out of a dictionary make sure it contains the key:

if (mydictionary.ContainsKey(mykey))
{
  Foo f = mydictionary[mykey];
  //work with f
}
This is bad approach. Not only it performs lookup twice, it still can throw an exception in multithreaded applications.

Much better approach (explicitly designed to cover the whole issue) is to leverage Dictionary.TryGetValue() method:

Foo f;
if (mydictionary.TryGetValue(mykey, out f))
{
  //work with f
}
Dictionary.TryGetValue() method returns true if the Dictionary contains an element with the specified key; otherwise, false. Moreover:
If the key is not found, then the value parameter gets the appropriate default value for the value type TValue; for example, 0 (zero) for integer types, false for Boolean types, and a null reference (Nothing in Visual Basic) for reference types.

Use the TryGetValue method if your code frequently attempts to access keys that are not in the dictionary. Using this method is more efficient than catching the KeyNotFoundException thrown by the Item property.

This method approaches an O(1) operation.

Ok, fine solution, but still remember than when moving from Hashtable to Dictionary<K, V> you have to check very carefully every single indexer usage to spot nonexisting key cases.

Related Blog Posts

No TrackBacks

TrackBack URL: http://www.tkachenko.com/cgi-bin/mt-tb.cgi/525

Leave a comment