C# Dictionary Best Practices And What To Avoid

Dictionary Best Practices And What To Avoid Page Banner Image

Introduction

Dictionary using best practices with the right key scales well over large datasets. Several pitfalls should be avoided. In C#, the dictionary is one of my favorite go-to data structures when I need top performance from my app.

Dictionary Add Key-Value Pairs

Add Function

To add new key value pairs we use the Add function from a dictionary object. It takes a key and value of any type. Values can be duplicated, but keys must be unique.

static void Main(string[] args)
{
    Dictionary<string, string> lockerNumberContendsDictionary = new Dictionary<string, string>();
    lockerNumberContendsDictionary.Add("5849", "backpack");
    lockerNumberContendsDictionary.Add("3425", "lunch bag");
    lockerNumberContendsDictionary.Add("434", "cell phone");
    lockerNumberContendsDictionary.Add("2", "basketball");
    foreach (string lockerNumber in lockerNumberContendsDictionary.Keys)
    {
        string contends = lockerNumberContendsDictionary[lockerNumber];
        Console.WriteLine($"Locker#:{lockerNumber}, Contends:{contends}");
    }
}
Code Output
Locker#:5849, Contends:backpack
Locker#:3425, Contends:lunch bag
Locker#:434, Contends:cell phone
Locker#:2, Contends:basketball

Another way to add key value pairs and my preferred way but either way works. This used the setter for the dictionary', by setting the value to the key it is also adding the key to the dictionary.

static void Main(string[] args)
{
    Dictionary<string, string> lockerNumberContendsDictionary = new Dictionary<string, string>();
    lockerNumberContendsDictionary["5849"] = "backpack";
    lockerNumberContendsDictionary["3425"] = "lunch bag";
    lockerNumberContendsDictionary["434"] = "cell phone";
    lockerNumberContendsDictionary["2"] = "basketball";
    Console.WriteLine($"Locker#:5849, Contends:{lockerNumberContendsDictionary["5849"]}");
    Console.WriteLine($"Locker#:3425, Contends:{lockerNumberContendsDictionary["3425"]}");
    Console.WriteLine($"Locker#:434, Contends:{lockerNumberContendsDictionary["434"]}");
    Console.WriteLine($"Locker#:2, Contends:{lockerNumberContendsDictionary["2"]}");
}
Code Output
Locker#:5849, Contends:backpack
Locker#:3425, Contends:lunch bag
Locker#:434, Contends:cell phone
Locker#:2, Contends:basketball

Add Exceptions

System.ArgumentException:An item with the same key has already been added

The following lines of code try to add 6 key-value pairs to the dictionary but the last two keys are duplicated and thus an exemption is thrown on line 8. To avoid this kind of exception we need to check the dictionary if the key exists already. Always check if the key exists in the dictionary before trying to add a new key-value pair.

static void Main(string[] args)
{
    Dictionary<string, string> lockerNumberContendsDictionary = new Dictionary<string, string>();
    lockerNumberContendsDictionary.Add("5849", "backpack");
    lockerNumberContendsDictionary.Add("3425", "lunch bag");
    lockerNumberContendsDictionary.Add("434", "cell phone");
    lockerNumberContendsDictionary.Add("2", "basketball");
    lockerNumberContendsDictionary.Add("3425", "tennis racket");
    lockerNumberContendsDictionary.Add("5849", "pillow");
}

Check if Key Exists Already

Before adding any key value combination to the dictionary check to see if the key already exists. Examine the code snippet below. There can not be two keys in the dictionary. Use the ContainsKey function to find if the key already exists in the dictionary.

public static bool CheckIfKeyExists(string key, string value, Dictionary<string, string> dictionary)
{
    if (!dictionary.ContainsKey(key))
    {
        dictionary.Add(key, value);
        return true;
    }
    else
    {
        return false;
    }
}

Next, we add items to this dictionary. Let’s assume that we have a set of locker numbers that can only hold one item each. We will attempt to add 6 items but if a locker number already exists in our dictionary then that item will not be added.

static void Main(string[] args)
{
    Dictionary<string, string> lockerNumberContendsDictionary = new Dictionary<string, string>();
    CheckIfKeyExists("5849", "backpack", ref lockerNumberContendsDictionary);
    CheckIfKeyExists("3425", "lunch bag", ref lockerNumberContendsDictionary);
    CheckIfKeyExists("434", "cell phone", ref lockerNumberContendsDictionary);
    CheckIfKeyExists("2", "basketball", ref lockerNumberContendsDictionary);
    CheckIfKeyExists("3425", "tennis racket", ref lockerNumberContendsDictionary);
    CheckIfKeyExists("5849", "pillow", ref lockerNumberContendsDictionary);
    foreach (string lockerNumber in lockerNumberContendsDictionary.Keys)
    {
        string contends = lockerNumberContendsDictionary[lockerNumber];
        Console.WriteLine($"Locker#:{lockerNumber}, Contends:{contends}");
    }
}

As we can see that unique keys can be added to the dictionary. The items tennis racket and pillow could not be added because those keys already exist.

Get Value

Accessing the dictionary is done by passing the key value in the brackets ‘[]’, which is called the indexer. The value is returned almost instantly without any search done. This speed is the main strength of the dictionary, this quick access to the values. You can see the syntax of the get value in lines 9-12 below.

static void Main(string[] args)
{
    Dictionary<string, string> lockerNumberContendsDictionary = new Dictionary<string, string>();
    lockerNumberContendsDictionary.Add("5849", "backpack");
    lockerNumberContendsDictionary.Add("3425", "lunch bag");
    lockerNumberContendsDictionary.Add("434", "cell phone");
    lockerNumberContendsDictionary.Add("2", "basketball");
    Console.WriteLine($"Locker#:5849, Contends:{lockerNumberContendsDictionary["5849"]}");
    Console.WriteLine($"Locker#:3425, Contends:{lockerNumberContendsDictionary["3425"]}");
    Console.WriteLine($"Locker#:434, Contends:{lockerNumberContendsDictionary["434"]}");
    Console.WriteLine($"Locker#:2, Contends:{lockerNumberContendsDictionary["2"]}");
}

Get Value Exceptions

System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary

This exemption comes when we try to get a value from a key that does not currently exists in the dictionary. See the example below, when the key “244324” was not added to the dictionary and then was it accessed.

static void Main(string[] args)
{
    Dictionary<string, string> lockerNumberContendsDictionary = new Dictionary<string, string>();
    lockerNumberContendsDictionary.Add("5849", "backpack"); lockerNumberContendsDictionary.Add("3425", "lunch bag");
    lockerNumberContendsDictionary.Add("434", "cell phone");
    lockerNumberContendsDictionary.Add("2", "basketball");
    Console.WriteLine($"Locker#:5849, Contends:{lockerNumberContendsDictionary["5849"]}");
    Console.WriteLine($"Locker#:3425, Contends:{lockerNumberContendsDictionary["3425"]}");
    Console.WriteLine($"Locker#:434, Contends:{lockerNumberContendsDictionary["434"]}");
    Console.WriteLine($"Locker#:2, Contends:{lockerNumberContendsDictionary["2"]}");
    Console.WriteLine($"Locker#:2444324, Contends:{lockerNumberContendsDictionary["2444324"]}");
}

There are two ways to guard against this exception. The first is the check to see if the key exists in the dictionary before trying to access that key.

public static string GetValueByCheckIfKeyExists(string key, ref Dictionary<string, string> dictionary)
{
    if (dictionary.ContainsKey(key))
    {
        return dictionary[key];
    }
    else
    {
        return "";
    }
}

The second safe way to get the value of a key is to use the TryGetValue function. I prefer this way too for two reasons. It checks if the key exists and returns true and the out parameter returns the value. This is slightly faster than checking for the key first and then getting the value in the previous method.

public static string GetValueByTryGetValue(string key, ref Dictionary<string, string> dictionary)
{
    string value = "";
    if (dictionary.TryGetValue(key, out value))
    {
        return value;
    }
    else
    {
        return "";
    }
}

The below example uses both protections against this exception. Both return the value when the key exists and both return an empty string when the key doesn’t exist in the dictionary. This would conclude the dictionary best practices of this collection type.

static void Main(string[] args)
{
    Dictionary<string, string> lockerNumberContendsDictionary = new Dictionary<string, string>();
    lockerNumberContendsDictionary.Add("5849", "backpack");
    lockerNumberContendsDictionary.Add("3425", "lunch bag");
    lockerNumberContendsDictionary.Add("434", "cell phone");
    lockerNumberContendsDictionary.Add("2", "basketball");
    Console.WriteLine($"GetValueByCheckIfKeyExists - Locker#:5849, Contends:{GetValueByCheckIfKeyExists("5849", ref lockerNumberContendsDictionary)}");
    Console.WriteLine($"GetValueByTryGetValue - Locker#:3425, Contends:{GetValueByTryGetValue("3425", ref lockerNumberContendsDictionary)}");
    Console.WriteLine($"GetValueByCheckIfKeyExists - Locker#:434, Contends:{GetValueByCheckIfKeyExists("434", ref lockerNumberContendsDictionary)}");
    Console.WriteLine($"GetValueByTryGetValue - Locker#:2, Contends:{GetValueByTryGetValue("2", ref lockerNumberContendsDictionary)}");
    Console.WriteLine($"GetValueByCheckIfKeyExists - Locker#:2444324, Contends:{GetValueByCheckIfKeyExists("2444324", ref lockerNumberContendsDictionary)}");
    Console.WriteLine($"GetValueByTryGetValue - Locker#:32354, Contends:{GetValueByTryGetValue("32354", ref lockerNumberContendsDictionary)}");
}
Code Output
GetValueByCheckIfKeyExists - Locker#:5849, Contends:backpack
GetValueByTryGetValue - Locker#:3425, Contends:lunch bag
GetValueByCheckIfKeyExists - Locker#:434, Contends:cell phone
GetValueByTryGetValue - Locker#:2, Contends:basketball
GetValueByCheckIfKeyExists - Locker#:2444324, Contends:
GetValueByTryGetValue - Locker#:32354, Contends:
Get Latest Updates
Comments Section