In this short blog post, I want to showcase three 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:
- You can forget to do that in new places or if you refactor
- You have this knowledge spread all over the place.
- 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;
}