Search code examples
c#collectionsdictionary

Dictionary returning a default value if the key does not exist


I find myself using the current pattern quite often in my code nowadays

var dictionary = new Dictionary<type, IList<othertype>>();
// Add stuff to dictionary

var somethingElse = dictionary.ContainsKey(key) ? dictionary[key] : new List<othertype>();
// Do work with the somethingelse variable

Or sometimes

var dictionary = new Dictionary<type, IList<othertype>>();
// Add stuff to dictionary

IList<othertype> somethingElse;
if(!dictionary.TryGetValue(key, out somethingElse) {
    somethingElse = new List<othertype>();
}

Both of these ways feel quite roundabout. What I really would like is something like

dictionary.GetValueOrDefault(key)

Now, I could write an extension method for the dictionary class that does this for me, but I figured that I might be missing something that already exists. SO, is there a way to do this in a way that is more "easy on the eyes" without writing an extension method to dictionary?


Solution


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


    TryGetValue will already assign the default value for the type to the dictionary, so you can just use:

    dictionary.TryGetValue(key, out value);
    

    and just ignore the return value. However, that really will just return default(TValue), not some custom default value (nor, more usefully, the result of executing a delegate). There's nothing more powerful built into the framework. I would suggest two extension methods:

    public static TValue GetValueOrDefault<TKey, TValue>(
        this IDictionary<TKey, TValue> dictionary,
        TKey key,
        TValue defaultValue)
    {
        return dictionary.TryGetValue(key, out var value) ? value : defaultValue;
    }
    
    public static TValue GetValueOrDefault<TKey, TValue>(
        this IDictionary<TKey, TValue> dictionary,
        TKey key,
        Func<TValue> defaultValueProvider)
    {
        return dictionary.TryGetValue(key, out var value) ? value : defaultValueProvider();
    }
    

    (You may want to put argument checking in, of course :)