How to get null instead of the KeyNotFoundException accessing Dictionary value by key?

Here is my solution from my personal library, implemented as an extension method. I am only posting it because it is implemented from the dictionary interface and allows an optional default value to be passed in.

Implementation

public static TV GetValue<TK, TV>(this IDictionary<TK, TV> dict, TK key, TV defaultValue = default(TV))
{
    TV value;
    return dict.TryGetValue(key, out value) ? value : defaultValue;
}

Usage

 MyDictionary.GetValue("key1");
 MyDictionary.GetValue("key2", -1);
 MyDictionary.GetValue("key3")?.SomeMethod();

You can't get the syntax you want with an extension method, and as others have said overriding a method/operator to change its behavior is generally not a great idea. I think the best you can do is shorten the name you use.

That's if you need to keep to the IDictionary interface. If you aren't interfacing with any code that expects an IDictionary, then you are free to define your own interface and having the [] operator work differently isn't a problem.

Whatever you end up calling the function, you'll want to implement it like this:

public static U Get<T, U>(this Dictionary<T, U> dict, T key)
    where U : class
{
    U val;
    dict.TryGetValue(key, out val);
    return val;
}

It just does one lookup, compared with 2 for your implementations.


In the end I came up with a variant using a deriving from dictionary class with explicit interface implementation:

public interface INullValueDictionary<T, U>
    where U : class
{
    U this[T key] { get; }
}

public class NullValueDictionary<T, U> : Dictionary<T, U>, INullValueDictionary<T, U>
    where U : class
{
    U INullValueDictionary<T, U>.this[T key]
    {
        get
        {
            U val;
            this.TryGetValue(key, out val);
            return val;
        }
    }
}

So it exposes the functionality I need the following way:

//create some dictionary
NullValueDictionary<int, string> dict = new NullValueDictionary<int, string>
{
    {1,"one"}
};
//have a reference to the interface
INullValueDictionary<int, string> idict = dict;

try
{
    //this throws an exception, as the base class implementation is utilized
    Console.WriteLine(dict[2] ?? "null");
}
catch { }
//this prints null, as the explicit interface implementation 
//in the derived class is used
Console.WriteLine(idict[2] ?? "null");

Tags:

C#

Dictionary