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

C#Dictionary

C# Problem Overview


In some certain scenario it appeared to be useful for me to have a short-spoken, readable way to get null instead of the KeyNotFoundException while accessing dictionary value by key, when there is no such key in the dictionary.

The first thing that came into my mind was an extension method:

public static U GetValueByKeyOrNull<T, U>(this Dictionary<T, U> dict, T key)
        where U : class //it's acceptable for me to have this constraint
{
    if (dict.ContainsKey(key))
        return dict[key];
    else 
        //it could be default(U) to use without U class constraint
        //however, I didn't need this.
        return null; 
}

But it's not very short-spoken actually, when you write something like this:

string.Format("{0}:{1};{2}:{3}",                                                 
              dict.GetValueByKeyOrNull("key1"),
              dict.GetValueByKeyOrNull("key2"),
              dict.GetValueByKeyOrNull("key3"),
              dict.GetValueByKeyOrNull("key4"));

I'd say, it would be much better to havesomething close to base syntax: dict["key4"].

Then I came up with an idea to have a class with a private dictionary field, which exposed the functionality I need:

public class MyDictionary<T, U> //here I may add any of interfaces, implemented
                                //by dictionary itself to get an opportunity to,
                                //say, use foreach, etc. and implement them
                                // using the dictionary field.
        where U : class
{
    private Dictionary<T, U> dict;

    public MyDictionary()
    {
        dict = new Dictionary<T, U>();
    }

    public U this[T key]
    {
        get
        {
            if (dict.ContainsKey(key))
                return dict[key];
            else
                return null;
        }
        set
        {
            dict[key] = value;
        }
    }
}

But it seems a little overhead to get the slight change in the basic behaviour.

One more workaround could be to define a Func in the current context like this:

Func<string, string> GetDictValueByKeyOrNull = (key) =>
{
    if (dict.ContainsKey(key))
        return dict[key];
    else
        return null;
};

so it could be utilized like GetDictValueByKeyOrNull("key1").

Could you, please, give me any more suggestions or help to choose a better one?

C# Solutions


Solution 1 - C#

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();

Solution 2 - C#

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.

Solution 3 - C#

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");

Solution 4 - C#

Add a DictionaryExtension class

public static class DictionaryExtension
{
	public static TValue GetValueOrDefault<TKey, TValue>
		(	this IDictionary<TKey, TValue> dictionary,TKey key)
	{
		TValue value;
		return dictionary.TryGetValue(key, out value) ? value : default(TValue);
	}
}

And it can return Default value if not found key in dictionary.

The Default is null if this is reference type .

_dic.GetValueOrDefault();

Solution 5 - C#

Worth pointing out that the HybridDictionary does this by default. You lose the generic typeing, but get the null-if-not-found functionality.

And (at least theoretically) you get performance benefits at low numbers of values, I think.

Solution 6 - C#

I premise by saying that I would not use this. The new keyword, while useful in this case, can create bugs which are really hard to find. Other than that, you can try this class.

class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public new TValue this[TKey key]
    {
        get
        {
            TValue value;
            return TryGetValue(key, out value) ? value : default(TValue);
        }
        set { base[key] = value; }
    }
}

Solution 7 - C#

I've done this before and it worked pretty well to just inherit the regular Dictionary class and just hide the indexer. It's really clean to do it this way so you automatically acquire all the reliability and familiarity of the Regular Dictionary class.

public class NullSafeDict<TKey, TValue> : Dictionary<TKey, TValue> where TValue : class
{
    public new TValue this[TKey key]
    {
        get
        {
            if (!ContainsKey(key))
                return null;
            else
                return base[key];
        }
        set
        {
            if (!ContainsKey(key))
                Add(key, value);
            else
                base[key] = value;
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhorghView Question on Stackoverflow
Solution 1 - C#Jared GView Answer on Stackoverflow
Solution 2 - C#bmm6oView Answer on Stackoverflow
Solution 3 - C#horghView Answer on Stackoverflow
Solution 4 - C#TimChangView Answer on Stackoverflow
Solution 5 - C#BrondahlView Answer on Stackoverflow
Solution 6 - C#e_neView Answer on Stackoverflow
Solution 7 - C#Michael SochaView Answer on Stackoverflow