Is there an IDictionary implementation that, on missing key, returns the default value instead of throwing?

The indexer into Dictionary throws an exception if the key is missing. Is there an implementation of IDictionary that instead will return default(T)?

I know about the TryGetValue() method, but that's impossible to use with LINQ.

Would this efficiently do what I need?:

myDict.FirstOrDefault(a => a.Key == someKeyKalue);

I don't think it will as I think it will iterate the keys instead of using a Hash lookup.


Indeed, that won't be efficient at all.

As per comments, in .Net Core 2+ / NetStandard 2.1+ / Net 5, MS added the extension method GetValueOrDefault()

For earlier versions you can write the extension method yourself:

public static TValue GetValueOrDefault<TKey,TValue>
    (this IDictionary<TKey, TValue> dictionary, TKey key)
{
    TValue ret;
    // Ignore return value
    dictionary.TryGetValue(key, out ret);
    return ret;
}

Or with C# 7.1:

public static TValue GetValueOrDefault<TKey,TValue>
    (this IDictionary<TKey, TValue> dictionary, TKey key) =>
    dictionary.TryGetValue(key, out var ret) ? ret : default;

That uses:

  • An expression-bodied method (C# 6)
  • An out variable (C# 7.0)
  • A default literal (C# 7.1)

If you're using .NET Core 2 or above (C# 7.x), the CollectionExtensions class is introduced and you can use the GetValueOrDefault method to get default value if key is not there in a dictionary.

Dictionary<string, string> colorData = new Dictionary<string, string>();
string color = colorData.GetValueOrDefault("colorId", string.Empty);

Carrying these extension methods can help..

public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key)
{
    return dict.GetValueOrDefault(key, default(V));
}

public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key, V defVal)
{
    return dict.GetValueOrDefault(key, () => defVal);
}

public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key, Func<V> defValSelector)
{
    V value;
    return dict.TryGetValue(key, out value) ? value : defValSelector();
}

Collections.Specialized.StringDictionary provides a non-exception result when looking up a missing key's value. It is also case-insensitive by default.

Caveats

It is only valid for its specialized uses, and — being designed before generics — it doesn't have a very good enumerator if you need to review the whole collection.