Dictionary Lookup and avoiding "KeyNotFound" Exception

In the old days when we used Hashtable, we would safely look up any item without having to worry about an Exception and crash. Code like the following was very common.

//where htable is a populated Hashtable
mValue = htable["some key"] as SomeType;
if(mValue != null)
{
    //Item was found in the Hashtable, process it
}
else
{
    //No Item was found with the Key
    //Do something else
}

With the generic Dictionary, this is no longer an option. If you try to look-up an item with a Key that does not exist, instead of returning null, a Dictionary will throw a KeyNotFound Exception. Because of this, simply replacing a Hashtable with a Dictionary in an existing Project is not safe. This is annoying, why does the Dictionary throw an Exception? Why not return a null just like the Hashtable? First I thought this was a feature by design, not by choice. But when we look into the implementation of this functionality, it appears to be a choice. Here is the code for the Indexer of Generic Dictionary:

As you can see, it was about to return default(TValue), and then like an after thought, the KeyNotFound Exception was added before that line! Anyways, The .Net Framework Documentation outlines two methods for looking up Items in a generic Dictionary: Either wrap the lookup within a try...catch block, or use the TryGetValue() Method. In any case, checking for null with a lookup to find out if an item exists for that Key is not an option. If you simply need to know if an Item exists for a given Key, you should use the Dictionary.ContainsKey(TKey) Method which return a boolean.

Avoiding the KeyNotFound Exception

The Dictionary will always throw a KeyNotFound Exception if the Key does not exist, if there is any chance of a look up with non existent Key, the only safe way is to wrap a look-up within a try...catch block. The Framework documentation suggests that if there is possibility of frequent lookups of non existent Key, you should rather use the TryGetValue() Method. My Tests indicate that initiating a try...catch block is not really more expensive (in terms of speed) unless you are catching the Exception. Here is what I mean:

Another option to avoid the KeyNotFound Exception could be the following approach:

//Where dictionary is a populated Dictionary<>
if (dictionary.ContainsKey("some key"))
{
    //Item exists
    mValue = dictionary["some key"];
}
else
{
   //Item does not exist!
}
//No chance of KeyNotFound Exception
//But this method is twice expensive!

While the Exception is avoided this way, this approach effectively results in two lookups, takes twice the time and should be avoided.

Using the TryGetValue() Method

The TryGetValue() Method is recommended when you are frequently looking up a Dictionary with keys that don't exist. This is similar to the TryParse() Methods. It always takes multiple lines of code, as follows:

//Using the Dictionary.TryGetValue() Approach
//Customer is the Value Type in the dictionary
Customer c = null;
if (dictionary.TryGetValue("some key", out c))
{
    //Item exists, and c now holds a reference to the item...
}
else
{
    //Item does not exist with the key
}

Alternative to Dictionary.TryGetValue(): the ValueOrDefault() Extension Method

Since TryGetValue() does not throw any Exception, no need to wrap it with a try...catch block. But If you don't like this idea of declaring and initializing a variable to use as an "out" parameter as much as I do, here is an Extension method to take us back to the Hashtable days:

Keeping with the MethodOrDefault() convention of Linq Extension Methods, this ValueOrDefault() Method returns an Item if available, otherwise returns null for reference Types, and default value for Value Types. With this, we can safely use a one line approach like we did with a Hashtable:

This concludes the discussion of efficient Dictionary Lookup. Was it any help to you?

Posted on January 27, 2010 11:49 by Haider

Comments

January 29. 2010 07:01

Marsia

Thanks!

I hate that KeyNotFound Exception popping up in older Projects because we replaced a Hashtable with a Dictionary...

Marsia

February 22. 2010 06:44

Smita

I still wonder what makes the generic Dictionary faster than a Hashtable? Isn't the Hashtable supposed to be the fastest data structure?

Smita

Don't Post SPAM

If you are posting a commment just to get a link, don't waste your time!

I have a sophisticated comment moderation system in place, and your comment will not be posted.

Add comment




biuquote
  • Comment
  • Preview
Loading