Dictionary is a handy class. It’s a collection of key-value pairs. It is a hash table which means that it has to have unique keys (according to equality comparer). Each key is mapped to a value. Retrieving a value by key is very fast. There are many things you can do with it. In this article I’m going to show you some tricks that may come in handy sometimes.

Initializing dictionary

In cases when you already have some predefined data you can initialize it using collection initializer.

1
2
3
4
5
var score = new Dictionary<string, int>
{
    { "A", 1 },
    { "B", 2 }
};

How to create case-insensitive dictionary

By default dictionaries are case sensitive, which means that dictionary["A"] and dictionary["a"] are different entries. You can however use overloaded constructor to make it case insensitive.

1
var d = new Dictionary<string, int>(StringComparer.OridinalIgnoreCase);

Get keys/values

You can get keys or values alone, it’s already built-in.

1
2
3
var score = new Dictionary<string, int>();
var keys = score.Keys;
var values = score.Values;

Looping over key-value pairs

Dictionary implements IEnumerable<TKey, TValue> so you can loop over it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var score = new Dictionary&lt;string, int&gt;
{
    { "A", 1 },
    { "B", 2 }
};

foreach(var pair in score)
{
    var k = pair.Key;
    var v = pair.Value;
}

Testing if dictionary contains key or value

You can test it by using built-it methods.

1
2
3
4
5
6
7
8
var score = new Dictionary&lt;string, int&gt;
{
    { "A", 1 },
    { "B", 2 }
};

var hasKey = score.ContainsKey("A");
var hasValue = score.ContainsValue(3);

Dictionary and LINQ

Good news is that you can still use Linq with dictionaries.

1
2
var students = new Dictionary&lt;string, Student&gt;();
var subset = students.Where(entry =&gt; entry.Key.StartsWith("A"));

How to merge dictionaries in C#

Key point with merging dictionaries is that there can be duplicates and, as we know, it will cause an exception. So we need to remember that we have to deal with duplicaties. As for the code, there are a few ways to do that. I’ll show you simple LINQ based solution, but you could as well just enumerate of it and add key-value pairs to a new one.

You can either use Union or Concat. Union technically tries to remove duplicates, but it won’t work for Dictionaries, because default IEqualityComparer cannot handle it. You can provide custom comparer as a second argument to Union, but this is not the solution I like.

We’ll use Concat, but to prevent duplicates we’re going to group (using GroupBy) results by keys and pick first value. Then we’ll convert it back to dictionary using ToDictionary extension method (notice how we select value).

1
2
3
4
5
6
7
8
9
var dict1 = new Dictionary&lt;string, int&gt;();
var dict2 = new Dictionary&lt;string, int&gt;();

var merged = dict1
                 .Concat(dict2)
                 .GroupBy(i =&gt; i.Key)
                 .ToDictionary(
                     group =&gt; group.Key, 
                     group =&gt; group.First().Value);

Replacing switch/case with dictionary

This technique came in hand multiple times for me. Instead of  large switch/case statement you can construct a dictionary which will work in the same manner. This alone saves some space. But if we take into account that we can add new entires to it during application execution then we have more elastic solution than (stiff) switch/case.

Here’s and example of mapping http codes to messages.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// this switch statment
int httpCode  = 415;
switch(httpCode)
{
    case 200:
        return "OK";
    case 404:
        return "Not found";
    default:
        return "Unknow code";
}
// can be refactored into this
int httpCode = 415;
var httpCodes = new Dictionary&lt;int, string&gt;
{
    { 200, "OK" },
    { 404, "Not found" }
};

httpCodes.TryGetValue(httpCode, out string result);
return result ?? "Unknown code";

Sorting a dictionary

Technically order of elements in a Dictionary is non-deterministic, which means that we cannot rely on it. If you add a few elements and then enumerate over dictionary it can be in different order.

You can order a elements in dictionary, but you will receive a separate collection of type IOrderedEnumerable<TElement>, the order of elements inside it will not be affected.

1
2
3
4
5
6
7
8
var score = new Dictionary&lt;string, int&gt;
{
    { "A", 1 },
    { "B", 2 }
};

IOrderedEnumerable&lt;KeyValuePair&lt;string, int&gt;&gt; sorted 
        = score.OrderBy(i =&gt; i.Value);

However there exists special SortedDictionary class, which sorts elements by keys. You can provide your own comparer implementation, refer to documentation.

1
var sorted = new SortedDictionary&lt;string, int&gt;();

Dictionary with ordered elements

There’s a specialized class for the purpose of having ordered items. It means that when you enumerate it, elements will always be in the same order as you added those inside it. It’s called OrderedDictionary and the order of items is guaranteed. It’s worth noting that there is no generic type version.

1
var ordered = new System.Collections.Specialized.OrderedDictionary();