Dictionary<TKey, TValue> vs. Hashtable() tip

If you're porting code from .NET 1.x to .NET 2.0, like I'm doing at the moment, and your .NET 1.x code uses Hashtables(), be aware of the following if you decide to migrate your Hashtables to Dictionary<TKey, TValue> variables.

In .NET 1.x, you'd do:

Hashtable myData = new Hashtable();
//... fill it

SomeType value = (SomeType)myData[key];
if(value==null)
{
   // key not there, handle...
}
now, if you port this to .NET 2.0, you normally end up with this code:
Dictionary<KeyType, SomeType> myData = new Dictionary<KeyType, SomeType>();
//... fill it

SomeType value = myData[key];
if(value==null)
{
   // key not there, handle...
}
Though, this doesn't work. It compiles ok, but something changed in .NET 2.0: if key isn't found, you no longer get null back but you get a nice exception. So the code above should be reworked to:
Dictionary<KeyType, SomeType> myData = new Dictionary<KeyType, SomeType>();
//... fill it

SomeType value = null;
if(!myData.ContainsKey(key))
{
   // key not there, handle...
}
else
{
   value = myData[key];
}
The sad part is: often the code to port isn't small, and you first try to get it compiled. If you don't keep the above difference in mind, you'll probably have a lovely time fixing bugs after the tests have run. So you've been warned

UPDATE: Wilco Bauwer posted in the comments another work-around, which is even more preferable: TryGetValue(). Sometimes you overlook the most obvious things!
Reworking my example above, it will look like:

Dictionary<KeyType, SomeType> myData = new Dictionary<KeyType, SomeType>();
//... fill it

SomeType value = null;
if(!myData.TryGetValue(key, out value))
{
   // key not there, handle...
}

5 Comments

  • You should use TryGetValue instead. It has an out parameter and returns true/false if the value was found. That way you will only be doing a single lookup.

  • What timing, I was just looking into this same problem. Thanks for the heads up.

  • Thanks Wilco, that's indeed another way to do it and even more efficient, I'll add that to the post.

  • This is another one of those cases where Microsoft is using Exception incorrectly, IMHO. A key not being in a collection should not be an 'exceptional' situation - it's quite common.



    While the fix is easy enough this is not nearly as logical as checking for null on a result, especially given that there was precedent.



    Lame to no end...



  • The problem with returning null is that a generic collection can hold instances of value types or reference types, whereas a non-generic collection only holds instances of objects (reference type). Therefore, the non-generic collection can return null and the answer will still be semantically correct for the output type, whereas in a generic collection null cannot be assigned to a value type, so that would break compatability.



    Perhaps MS could have supplied some kind of workaround that used nullable types when dealing with value types. I agree, this is certainly no place for an exception. Exceptions are supposed to be for exceptional circumstances! Major design flaw.

Comments have been disabled for this content.