Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any sort of generic dictionary where attempting to get a non-existent key will return null? [duplicate]

It really annoys me that I must use .ContainsKey instead of just doing a value==null in a dictionary. Real life example:

var dictionary = new Dictionary<string, FooBar>();
var key = "doesnt exist";
var tmp = dictionary[key] ?? new FooBar(x, y);

Instead, I have these choices:

var key = "doesnt exist";
FooBar tmp = null;
if (dictionary.ContainsKey(key))
{
    tmp = dictionary[key];
} else {
    tmp = new FooBar(x, y);
}

Or this:

FooBar tmp = null;
if (!Dictionary.TryGetValue(key, out tmp))
{
    tmp = new FooBar(x, y);
}

To me, this code is extremely verbose. Is there a built-in generic class which implements IDictionary (or otherwise allows key-value type access) but doesn't throw an exception when I try to lookup a key, and instead return null?

like image 399
Earlz Avatar asked Dec 26 '22 15:12

Earlz


1 Answers

The problem is that Dictionary<TKey, TValue> allows you to store null as a value, thus you wouldn't know if the key didn't exist, or just had a value of null. The other problem is that null is only valid for TValue types that are reference types (or Nullable<T>).

Now, that said, you could write an extension method yourself to do so:

public static class DictionaryUtilities
{
    public static TValue SafeGet<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue defaultIfNotFound = default(TValue))
    {
        TValue value;

        return dict.TryGetValue(key, out value) ? value : defaultIfNotFound;
    }
}

In this way, you could query your dictionary like this:

var sample = new Dictionary<int, string> { {1, "One"}, {2, "Two}, {3, "Three"} };

var willBeNull = sample.SafeGet(4);

var willBeHi = sample.SafeGet(4, "HI!");

Though, of course, the above code would return the default of value types if TValue was a value type (that is, if the value type was int, it would return 0 on not found, by default.)

Again, though, you could create two forms, one where TValue is constrained to class and one to struct that would allow you to return a Nullable<T> for value types...

like image 111
James Michael Hare Avatar answered May 10 '23 09:05

James Michael Hare