Wilsonhut

Deal with it or don't

Obvious Methods: IDictionary Get – with defaults

Most of this blog is just obvious extension methods. Here’s another.

I was writing this code today:

var mappedValue = mapDictionary.ContainsKey(value) ? mapDictionary[value] : defaultMapValue;

I immediately knew I was going to find an existing method on IDictionary, or write an extension method for this. I couldn’t find an existing one, so I wrote one. Now my code looks like this:

var mappedValue = mapDictionary.Get(value, defaultMapValue);

It takes the key that I want the value for, and a value to return if the key is not found.

IEnumerable has an ElementAtOrDefault method that returns the default value for the type, so I wrote an overload for my method that returns the default value for the type, too. (It returns null for reference types, like strings, and return zero for ints, etc…)

I figured I needed another overload or two that take a Func to get the default value for use in the case where getting the default value is not trivial.

So here’s my suite of three IDictionary.Get methods:

  public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> getDefaultValue)

  {

    TValue value;

    return dictionary.TryGetValue(key, out value) ? value : getDefaultValue(key);

  }

  public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> getDefaultValue)

  {

    return dictionary.Get(key, k => getDefaultValue());

  }

  public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)

  {

    return dictionary.Get(key, k => defaultValue);

  }

  public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)

  {

    return dictionary.Get(key, k => default(TValue));

  }

How do you use it?  How about I provide a completely contrived example? Let’s say you have this list of state abbreviations and state names that begin with the letter ‘A’ in a Dictionary, but we don’t have the rest of the states:

var aStates = new Dictionary<string, string>{{"AL", "Alabama"}, {"AK", "Alaska"}, {"AZ", "Arizona"}, {"AR", "Arkansas"},};

Now lets say you have another list of state abbreviations, and you want to get the names for them.

new[]{"AL", "AR", "TN", "AZ"}.Select(s => aStates.Get(s, "Some non-A state"));

Run that, and you get an IEnumerable with the following:

Alabama
Arkansas
Some non-A state
Arizona

If you use the overload that doesn’t take a default…

new[]{"AL", "AR", "TN", "AZ"}.Select(s => aStates.Get(s));

…you’d see a NULL for the “TN” value.

Alabama
Arkansas
null
Arizona

You could use the overload that takes a Func to call some service that gets the state name for the abbreviation.

new[]{"AL", "AR", "TN", "AZ"}.Select(s => aStates.Get(s, StateService.GetByAbbreviation));

…and it only gets called when it’s needed.

Maybe it would be cool to write one that adds “TN” to the underlying dictionary after the service is called, so that it doesn’t have to call the service again for “TN”. (Caching!) [Edit. Done: Obvious Methods: IDictionary Get – with defaults plus]

Advertisements

One response to “Obvious Methods: IDictionary Get – with defaults

  1. Pingback: Obvious Methods: IDictionary Get – With Defaults plus | Wilsonhut

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: