views:

458

answers:

6

If I'm using a Hashtable, I can write code like this:

object item = hashtable[key] ?? default_value;

That works whether or not key appears in the Hashtable.

I can't do that with a Dictionary<TKey. TValue>. If the key's not present in the dictionary, that will throw a KeyNotFoundException. So I have to write code like this:

MyClass item;
if (!(dict.TryGetValue(key, out item))
{
   item = default_value;
}

I'm wondering why this is. Dictionary<TKey, TValue> is just a wrapper around Hashtable. Why has this restriction been added to it?

Edit:

For another perspective on PopCatalin's answer (see below), the code I'd written above won't work if the dictionary's values are of a value type. If I'm using a Dictionary<int, int>, then the code I would like to use looks like this:

int i = dict[key] ?? default_value;

And that won't compile, because dict[key] isn't a nullable or reference type.

A: 

I am pretty sure that this restriction is one of the functional reasons for the creation of the wrapper in the first place.

Sparr
+1  A: 

If you look to the code using Reflector you'll see that Dictionary tries to find the key and explicitly raises an exception if it doesn't find the key.

public TValue get_Item(TKey key)
{
    int index = this.FindEntry(key);
    if (index >= 0)
    {
        return this.entries[index].value;
    }
    ThrowHelper.ThrowKeyNotFoundException();
    return default(TValue);
}
Otávio Décio
+4  A: 

There is one misconception in your post. Dictionary is not a wrapper around Hashtable. It's a completely different implementation.

The reason why this change was made is mainly justified by one assertion: Null is a valid value for a hashtable. Without this change it's not possible to distinguish between a non-exsistent key and a value key with a null value using the [] method of access. Dictionary clears this up.

JaredPar
+1 because I've never looked in a dictionary and not said "WTF?" when I didn't find the word I was looking for.
Peter LaComb Jr.
JaredPar, if I examine System.Collections.DictionaryBase in Reflector, I see that it's using a Hashtable as its underlying data structure. Am I looking at the wrong thing?
Robert Rossney
I'll answer my own question: Dictionary<TKey, TValue> doesn't derive from DictionaryBase. I don't know why I was so sure it did, but I was wrong.
Robert Rossney
+1  A: 

Dictionary.ContainsKey is probably better for you than TryGetValue.

But as to why, no idea.

Sekhat
+2  A: 

I wrote an extension for this.

public static class DictionaryExtension
{
 public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> items, string key)
 {
  if (items != null && items.ContainsKey(key))
  {
   return items[key];
  }

  return default(TValue);
 }
}
Mike Geise
+5  A: 

The difference between a Dictionary<T> and a Hashtable is that a Dictionary<T> is a generic type that can specialize to store value types along reference types.

The hashtable can only store reference types (a Object passed by reference) and only value types that are boxed (also passed by reference).

When a dictionary is specialized with value types, it must return those values 'by value' not by reference.So, therefore, a Dictionary<T> can't return null, as null is not a valid value for value types.

Pop Catalin