C# Dictionary: Complete Guide [2023]

By Josip MiskovicUpdated on
A thumbnail showing C# code. Everything you need to know about C# Dictionary.

This article is a complete guide to the Dictionary data structure in C#.

C# Dictionary is a data structure that holds key-value pairs. It's called a Dictionary because the key is used to look up the corresponding value, just like in a real dictionary. The good thing is that the dictionary is a generic, so we can use it to store values of any type.

C# Dictionary Example

Initialization

To initialize a dictionary in C#, we first need to provide the type for the key and the type for the value.

For example, for a dictionary that stores the name and age of a person, the initialization would be:

C#
Dictionary<string, int> nameToAge = new Dictionary<string, int>();

The first type inside the angle brackets is the key type. The second type is the value type.

Initial values

To define initial values at the time of initialization, we use the following syntax:

C#
Dictionary<string, int> nameToAge = new Dictionary<string, int>()
{
	{"John", 26},
	{"Anna", 34 }
};

The collection-initializer syntax above is like the initialization of an array.

Another way to initialize a dictionary is object initializer introduced in C# 6:

C#
Dictionary<string, int> nameToAge = new Dictionary<string, int>
{
	["John"] = 26,	
	["Anna"] = 34
};

Add item to a dictionary

To add an item to a dictionary, we use the Add method. For example:

C#
nameToAge.Add("Adam", 24);

This would add "Adam" and his age of 24 to the nameToAge dictionary.

Remove the dictionary item

To remove an item from a dictionary, we use the Remove method. For example:

C#
nameToAge.Remove("Adam");

This would remove "Adam" from the nameToAge dictionary.

The remove method uses the key to determine which item to remove.

Update dictionary items

To update an item in a dictionary, we update the value associated with the key. For example:

C#
nameToAge["Adam"] = 24;

This would update Adam's age of 24 to nameToAge dictionary.

Remove all dictionary values

To remove all the values from a dictionary, we use the Clear method.

For example:

C#
nameToAge.Clear();

This would clear nameToAge dictionary of all items.

Get the number of elements

To get the number of items in the dictionary, we use the Count property.

For example:

C#
int count = nameToAge.Count;

This would get the number of items in nameToAge dictionary.

Duplicate values

In C#, a dictionary can only have one value for a key.

If we add another value with the same key, then we'll get the KeyNotFoundException exception.

For example, if we try to add a value with key "Adam" then we would get:

C#
Dictionary<string, int> nameToAge = new ()
{
	{"Adam", 26},
};
nameToAge.Add("Adam", 24);

Here we get the exception because there is already a key "Adam" and the dictionary cannot have two values for the same key.

As developers, we need to handle these exceptions by first checking for the key to exist before adding a value.

To check if a dictionary already has a value, we can use the ContainsKey method:

C#
nameToAge.ContainsKey("Adam")

It's a good design practice to use values we know are unique.

In the example above, it would be better to use a unique ID instead of a name.

C# Dictionary: Get value by key

To retrieve a value from a dictionary in C#, you can use the TryGetValue method or the indexer.

TryGetValue

The TryGetValue method is a safe way to get a value from a dictionary without having to handle exceptions.

It returns a bool value to let us know if the key was found.

For example, we can use TryGetValue this way:

C#
int age = nameToAge.TryGetValue("Adam", out int a) ? a : default;

The code above will first check if the dictionary has a key "Adam" and if it does, returns its value. If it does not, then age will be set to the default value for int, which is 0.

The "Try" pattern is very common in C# and .NET, I explained it in detail in my article on TryParse.

Indexer

Here's an example of how to get a dictionary value by key:

C#
Dictionary<string, int> dictionary = new Dictionary<string, int>();

dictionary.Add("apple", 1);
dictionary.Add("banana", 2);

int value = dictionary["apple"];
Console.WriteLine(value);  // Output: 1

Note that if you try to use the indexer to retrieve a value for a key that does not exist in the dictionary, it will throw a KeyNotFoundException. To avoid this, you can use the ContainsKey method to check if the key is present in the dictionary before trying to retrieve the value.

Iterate over a Dictionary

To iterate over keys and values of a dictionary, we can use the foreach loop:

C#
foreach (KeyValuePair<int, string> item in nameToAge)
{

  item.Key;
  item.Value;

}

The item variable is an object of type KeyValuePair<Tkey, TValue> which has the properties to provide the key and value.

KeyValuePair is a very simple struct. It only holds two properties - Key and Value:

KeyValuePair implementation.

Get keys and values

Dictionary exposes two read-only properties to get all keys or values:

These properties are useful if we want to iterate over all keys or values of a dictionary.

Keys and values source code.

Internals

C# dictionary uses a hash table as its internal data structure.

Hash tables rely on hash codes to locate an item.

For example, adding an item to a dictionary performs these 3 steps in the background:

  1. Compute a hash code for the key.
  2. Verify the key's hash code is not equal to the key already in the dictionary.
  3. Place the entry in the hash table bucket.

Read my article on Hashset to find out more about hash codes.

Dictionary and HashTable source code.

Use immutable objects for keys

A dictionary can break if we use a reference type as a key.

That's because Dictionary stores a reference to that object and not the object itself.

So if we change the object after adding it to the dictionary, then we would break the whole dictionary.

Because of that, it's a best practice to use immutable objects, like strings, when using the dictionary.

C# 9.0 in a Nutshell explains why:

If an object’s hashcode changes after it’s been added as a key to a dictionary, the object will no longer be accessible in the dictionary.

TryGetValue vs ContainsKey+Item

TryGetValue and ContainsKey are the two most popular ways of getting a value from a dictionary.

For ContainsKey, it's a two-step process:

  1. Do the lookup to verify the key exists in the dictionary.
  2. Do the lookup to get the value from the dictionary based on the key.

On the other hand, TryGetValue does the lookup and gets the value in one step.

Because of the performance, we should always use TryGetValue to get a value from a dictionary.

Dictionary exceptions

These are the most common exceptions we can get from a dictionary:

Exception typeException occurs
KeyNotFoundExceptionIf there is no key with the value we are looking up.
ArgumentOutOfRangeExceptionIf the index that we are looking up is out of range.
ArgumentNullExceptionIf the key is null.
ArgumentExceptionIf we try to add a key that already exists.

To prevent these exceptions, use TryGetValue and TryAdd.

Dictionary vs OrderedDictionary

The main difference between Dictionary and OrderedDictionary is that Dictionary does not guarantee the order in which it will return values, but OrderedDictionary does.

OrderedDictionary is less efficient than Dictionary because insert/delete operations have to be done on an array, with the complexity of O(n) at worst.

Dictionary vs SortedDictionary

SortedDictionary is another class that implements IDictionary.

The main difference between a Dictionary and SortedDictionary is that SortedDictionary uses a binary search tree with O(log n) retrieval, while Dictionary is a hash table of O(1) complexity for access.

Use SortedDictionary if you have an extensive list of items and need them sorted.

ReadOnlyDictionary

ReadOnlyDictionary is an implementation of IDictionary that does not allow adding or deleting items.

It only provides read access through its properties

ReadOnlyDictionary is a decorator wrapper around the regular Dictionary class.

C# Dictionary Performance

The following table shows the complexity of each IDictionary implementation:

ImplementationComplexity
Dictionary, OrderedDictionaryO(1)
SortedDictionaryO(log n)
ListO(n)

Historically, computer scientists have been exploring the most efficient way of searching through a dictionary. Richard Bornat from Middlesex University explained the problem here:

Lecture from Richard Bornat about dictionaries.

Concurrency

The Dictionary implementation is not thread-safe.

For example, one thread can change the data structure while another thread tries to iterate, causing an exception.

To make a thread-safe dictionary in C#, use the ConcurrentDictionary implementation.

All public and protected members of ConcurrentDictionary are thread-safe and we can use them concurrently from multiple threads.

The ConcurrentDictionary implementation uses tables to keep track of dictionary's state:

ConcurrentDictionary class implementation in .NET

Summary

The Dictionary data structure in C# is a collection of key-value pairs.

It's called a Dictionary because the key is used to look up the corresponding value, just like in a real dictionary.

We can initialize the Dictionary using either a collection-initializer or an object initializer.

To manage a dictionary, we use:

  • Add method
  • Remove method
  • Clear method
  • Update the value associated with the key

Be careful and catch exceptions when using any of the methods that change the structure, such as Add, Remove, Clear, or Update.

The most common way to retrieve a value from a dictionary is using TryGetValue, which gets a value without throwing exceptions.

Besides the standard Dictionary, there are other implementations of IDictionary interface:

  • The Dictionary class does not guarantee the order in which it will return values, but OrderedDictionary does.
  • ReadOnlyDictionary does not allow adding or deleting items.
  • ConcurrentDictionary uses tables to keep track of the dictionary's state from multiple threads, making it thread-safe.

FAQ

How do I create a dictionary from a list or array in C#?

To create a dictionary from a list or array in C#, you can use the ToDictionary method from the System.Linq namespace. This method takes a sequence of elements and a function that specifies how to create the key and value for each element.

Here's an example of creating a dictionary from a list of strings:

C#
List<string> list = new List<string> { "apple", "banana", "cherry" }; 
Dictionary<int, string> dictionary = list.ToDictionary(i => list.IndexOf(i), i => i);
foreach (KeyValuePair<int, string> kvp in dictionary) 
{
   Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}"); 
} 

Output:

Key: 0, Value: apple
Key: 1, Value: banana
Key: 2, Value: cherry

You can also use the ToDictionary method to create a dictionary from an array of elements.

C#
string[] array = new string[] { "apple", "banana", "cherry" };
Dictionary<int, string> dictionary = array.ToDictionary(i => Array.IndexOf(array, i), i => i);
foreach (KeyValuePair<int, string> kvp in dictionary) 
{
  Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}");
} 

Output:

Key: 0, Value: apple
Key: 1, Value: banana
Key: 2, Value: cherry

Note that if the key function returns duplicate keys for two or more elements, the ToDictionary method will throw an exception.

What are valid C# dictionary keys?

In C#, all keys that match the type of the dictionary are valid.

The only catch to be aware of is that the key cannot be null.

If we try to use null as a key, then we'll get an ArgumentNullException exception:

System.ArgumentNullException: Value cannot be null. (Parameter 'key')

Can we have a dictionary inside a dictionary?

Dictionary can have a dictionary as its value.

For example:

C#
Dictionary<string, Dictionary<int, string>> nameToAgeByBirthDate = new Dictionary<string, Dictionary<int, string>>();

Here nameToAgeByBirthDate has 2 key-value pairs.

Even though C# supports nested dictionaries, I prefer to avoid them.

It makes the code more complex with no benefit. A list or array is always a better choice.

Can key and value be of the same type?

In C#, the key and value of a dictionary can have the same type. For example, to create a string-to-string mapping, we can use a Dictionary<string, string>.

Josip Miskovic
About Josip

Josip Miskovic is a software developer at Americaneagle.com. Josip has 10+ years in experience in developing web applications, mobile apps, and games.

Read more posts →

Last modified on:
Download Free Software Developer Career Guide

I've used these principles to increase my earnings by 63% in two years. So can you.

Dive into my 7 actionable steps to elevate your career.