Three tricks with Dictionary

13/07/2023

In this short blog post, I want to showcase two nice tricks you can do with everybody's favorite data type: the dictionary.

It is a versatile data structure, and we can make it even more versatile!

Trick 1: Pass a StringComparer to the constructor

When you're handling strings as keys, it can happen that you don't really care if they are uppercase or lowercase - so you want to have a case-insensitive key collection.

Sure, you could do ToLower or ToUpper everywhere you ask for a key, but there are multiple problems:

  1. You can forget to do that in new places or if you refactor
  2. You have this knowledge spread all over the place.
  3. Useless allocations you wouldn't need

So a better choice is to pass in a StringComparer as a constructor argument to the Dictionary itself. Showing clearly the intent in a single point:

var dictionary = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase)
{
    { "foo", 1 },
    { "bar", 2 }
};

_ = dictionary.ContainsKey("FOO"); // true
_ = dictionary.ContainsKey("Foo"); // true
_ = dictionary.ContainsKey("foo"); // true
_ = dictionary["FOO"]; // 1
_ = dictionary["Foo"]; // 1

Trick 2: TryGetValue

TryGetValue is a nice method to get a value from a dictionary without having to check if the key exists first. It returns a bool indicating if the key was found and the value is written to an out parameter. So instead of writing the following:

Dictionary<string, int> dictionary = GetDictionary();
if (dictionary.ContainsKey("foo"))
{
    var value = dictionary["foo"];
    // do something with value
}

You can write the following:

Dictionary<string, int> dictionary = GetDictionary();
if (dictionary.TryGetValue("foo", out var value))
{
    // do something with value
}

Trick 3: Using GetValueOrDefault When Key Does Not Exist

If you attempt to get a value from a dictionary using a key that doesn't exist, it throws a KeyNotFoundException. But there is an extension, called GetValueOrDefault method to return a default value when the key doesn't exist:

Dictionary<int, string> dictionary = new()
{
    { 1, "foo" }
};

_ = dictionary.GetValueOrDefault(1, "not found"); // foo
_ = dictionary.GetValueOrDefault(2, "not found"); // not found

You could build this function on your own like this:

public static TValue GetValueOrDefault<TKey, TValue>(
  this Dictionary<TKey, TValue> dictionary,
  TKey key,
  TValue fallback)

{
  if (dictionary.TryGetValue(key, out TValue value))
  {
    return value;
  }

  return fallback;
}
26
An error has occurred. This application may no longer respond until reloaded. Reload x