C# Advanced

C# Dictionary

The objective of this article is to familiarize you with the generic C# Dictionary, which is implemented via Dictionary<TKey, TValue> collection class. You will learn how to declare, create, instantiate and use this type of collection, including code examples of the commonly used methods and properties of Dictionary<> class. Finally, different ways to iterate through all the items of the collection.

Table of Contents

What Is the Dictionary in C#?

C# Dictionary<TKey, TValue> is a type-safe generic collection class, which is used to store the data in a key value format. Key must be unique and it cannot be null whereas value can be duplicate and null. Each item in the dictionary is treated as KeyValuePair<TKey, TValue> structure that associates a key to a value. You can quickly find a value by specifying the key to search for, and you can use array notation to get the associated value. The main feature of dictionaries is the fast lookup based on keys.

C# Dictionary can be implemented with the Dictionary<TKey, TValue> class in the System.Collections.Generic namespace, where TKey and TValue are the type parameters to specify the type of items in the Dictionary. This namespace also includes the SortedDictionary<TKey, TValue> collection type, which maintains the collection in order, sorted by the keys.

Note: Every key in a Dictionary<TKey, TValue> must be unique. A key cannot be null, but a value can be, if the type of values in the list, TValue, is a reference type.


Properties and Methods of Dictionary Class

Mostly used methods of the Dictionary<> class to perform different operations are listed below.

C# Dictionary

You can declare and initialize a C# dictionary as in the following code.

using Statement

To work with the C# dictionary, you need to add the following namespace at the beginning your code:

using System.Collections.Generic;

How Do You Create a Dictionary in C#?

You can create C# Dictionary using either one or two statements.

Declare and Initialize C# Dictionary Using Two Statements

TKey and TValue are the generic data type parameters, where TKey is the type of the Key and TValue is the type of the value. This part of the declaration indicates that the class will work with a certain type.

Dictionary<TKey, TValue> dictName; // declaration

You use new keyword with default constructor to initialize an empty dictionary.

dictName = new Dictionary<TKey, TValue>(); // initialization

Declare and Initialize C# Dictionary on a Single Line

Dictionary<TKey, TValue> dictName = new Dictionary<TKey, TValue>(); // declaration & initialization

Use of var keyword to infer its type from the value that’s assigned to it.

var dictName = new Dictionary<TKey, TValue>();

C# Collection Initializers

You can assign values to collections using collection initializer syntax introduced in C# 3.0. It is a shortened syntax to create an instance of a collection. With a collection initializer, the values can be assigned all at once during the declaration using curly brackets notation. When the C# compiler encounters a collection initializer, it’ll replace the shorthand initializer syntax by appropriate method calls to the Add method.

Notice that because each item of a dictionary consists of three values, each item is enclosed in braces within the outer braces.

Here, you can specify each key/value pair as an anonymous type in the initializer list, like this:

Dictionary<int, string> planets = new Dictionary<int, string>() {
    { 1, "Mercury" },
    { 2, "Venus" },
    { 3, "Earth" }
};

If no parameters are passed in the constructor, then parentheses () following the data type are optional.

Dictionary<int, string> planets = new Dictionary<int, string> {
    { 1, "Mercury" },
    { 2, "Venus" },
    { 3, "Earth" }
};

The following collection initializer uses C# object initializers to initialize objects of the Planet class. Individual object initializers are enclosed in braces and separated by commas. Here, you are using int data type as the key (key can be any type) and a Planet type as the value.

var planets = new Dictionary<int, Planet> {
    { 101, new Planet() { Id = 1, Name = "Mercury" } },
    { 102, new Planet() { Id = 2, Name = "Venus" } },
    { 103, new Planet() { Id = 3, Name = "Earth" } }
};

Run Demo


C# Index Initializers (indexer notation)

C# 6 introduced a new feature called index initializer if a collection supports indexing, where you don’t need key and value within braces { }. Instead, you use the key within brackets [ ] followed by assignment operator (=) to assign value to that key.

Note: The new initializer syntax calls the indexer method to add and replace items to the collection.

//With an index initializer inside a collection initializer
Dictionary<int, string> planets = new Dictionary<int, string>()
{
    [1] = "Mercury",
    [2] = "Venus",
    [3] = "Earth"
};

To make your code more readable, I recommend that you use the indexer notation wherever possible to initialize a dictionary type.

Run Demo


Add Items to C# Dictionary

Dictionary<int, string> planets = new Dictionary<int, string>();

Add()

Use the Add method to add an item to the list. When you add an item to a dictionary, you specify the key along with the value assigned to that key.

Signature: void Add(TKey key, TValue value)

//With separated statements
planets.Add(1, "Mercury");
planets.Add(2, "Venus");
planets.Add(3, "Earth");

Run Demo

OUTPUT

1, Mercury
2, Venus
3, Earth

Every key in a Dictionary<TKey, TValue> must be unique, meaning you cannot use duplicate keys in the list. Any attempt to do that will result an exception ArgumentException with the message ‘An item with the same key has already been added. Key: 3’

// Different key but same value
planets.Add(4, "Earth");

//Same key but different value
planets.Add(3, "Mars"); // Exception

Run Demo

Using add method to add individual objects of Planet class.

Dictionary<int, Planet> planets = new Dictionary<int, Planet>();

var jupiter = new Planet();
jupiter.Id = 1;
jupiter.Name = "4 line: Mercury";
planets.Add(101, jupiter);

//Above 4 lines vs below 1 line syntax. Same result
planets.Add(102, new Planet() { Id = 2, Name = "1 line: Mercury" });

Run Demo

OUTPUT

101, 1 : 4 line: Mercury
102, 2 : 1 line: Mercury

Key Indexer to Add and Update Items

If a key does not exist, setting the indexer for that key adds a new key/value pair in the dictionary.

planets = new Dictionary<int, string>();

// using array notation
planets[1] = "Mercury";
planets[2] = "Venus";
planets[3] = "Earth";

You can use the square brackets [ ] notation to add a key/value pair. If the key has already been added, any existing value with the same key will be replaced by the new value without the danger of an exception.

planets[3] = "Earth - Updated";

Run Demo

OUTPUT

1, Mercury
2, Venus
3, Earth- Updated


Remove Items from C# Dictionary

var planets = new Dictionary<int, string>()
{
    [1] = "Mercury",
    [2] = "Venus",
    [3] = "Earth"
};

Remove()

The Remove method removes a particular item from the list. This method takes in one argument and removes the first occurrence of that argument. You need to pass the key to remove.

Signature: bool Remove(TKey key)

planets.Remove(2);

Run Demo

OUTPUT

1, Mercury
3, Earth

Clear()

The Clear method removes all the items in a list and sets its Count property to zero.

Signature: void Clear()

planets.Clear();

Run Demo


C# Dictionary Methods

var planets = new Dictionary<int, string>()
{
    [1] = "Mercury",
    [2] = "Venus",
    [3] = "Earth"
};

ContainsKey()

You can test whether a Dictionary<TKey, TValue> collection already contains a particular key by using the ContainsKey method, which returns Boolean (True/False) value.

Signature: bool ContainsKey(TKey key)

planets.ContainsKey(2); // Returns True

Run Demo

OUTPUT

True

ContainsValue()

Method checks and returns Boolean (True/False) value that indicates whether or not the dictionary contains the specified value.

Signature: bool ContainsValue(TValue value)

planets.ContainsValue("Venus"); // Returns True

Run Demo

OUTPUT

True

TryGetValue()

Gets the value associated with the specified key.

Note: You can also use an indexer of the Dictionary<TKey, TValue> class instead of TryGetValue to access a value stored in the dictionary.

Signature: bool TryGetValue(TKey key, out TValue value)

string value = string.Empty;
planets.TryGetValue(3, out value);

OUTPUT

Earth

// Or

if (planets.TryGetValue(4, out value))
    Console.WriteLine(value);
else
    Console.WriteLine("Key not found");

Run Demo

OUTPUT

Key not found


C# Dictionary Properties

var planets = new Dictionary<int, string>()
{
    [1] = "Mercury",
    [2] = "Venus",
    [3] = "Earth"
};

Count

To get the total number of key/value pairs contained in the Dictionary<TKey, TValue>, use the Count property.

planets.Count; // Returns 3

Run Demo

Keys

To get a collection containing the keys in the Dictionary<TKey, TValue>, use the Keys property.

foreach (var key in planets.Keys)
    Console.WriteLine(key);

The items of the KeyCollection are strongly typed with the type that was specified for dictionary keys.

// Or copy all the keys and then iterate
Dictionary<int, string>.KeyCollection keys = planets.Keys;

foreach (var key in keys)
    Console.WriteLine(key);

Run Demo

OUTPUT

1
2
3

Values

To get a collection containing the values in the Dictionary<TKey, TValue>, use the Values property.

foreach (var value in planets.Values)
    Console.WriteLine(value);

The items of the ValueCollection are strongly typed with the type that was specified for dictionary values.

// Or copy all the values and then iterate
Dictionary<int, string>.ValueCollection values = planets.Values;

foreach (var value in values)
    Console.WriteLine(value);

Run Demo

OUTPUT

Mercury
Venus
Earth


Indexer to Access Individual C# Dictionary Item

var planets = new Dictionary<int, string>()
{
    [1] = "Mercury",
    [2] = "Venus",
    [3] = "Earth"
};

You can access the dictionary items individually by using key indexer method. Key is used inside the square brackets [ ] to get the associated value.

Syntax

dictName[key];
planets[3];

OUTPUT

Earth

Run Demo

If you try to access an item with an indexer and passing a key that does not exist, an exception of type KeyNotFoundException is thrown with the message ‘The given key ‘4’ was not present in the dictionary.’.

planets[4]; // throw exception

To avoid that exception, you can use the method ContainsKey, which returns true if the key passed exists in the collection, or you can invoke the method TryGetValue, which tries to get the value but doesn’t throw an exception if key isn’t found:

// ContainsKey() method
if (planets.ContainsKey(4)) // Replace 4 with 3 
    Console.WriteLine(planets[4]);
else
    Console.WriteLine("Key not found");


// TryGetValue() method
string value = "";
if (planets.TryGetValue(4, out value)) // Replace 4 with 3
    Console.WriteLine(value);
else
    Console.WriteLine("Key not found");

Run Demo

OUTPUT

Key not found


Processing C# Dictionary with Loops

The first statement declares a dictionary named planets that contains 3 values.

var planets = new Dictionary<int, string>()
{
    [1] = "Mercury",
    [2] = "Venus",
    [3] = "Earth"
};

Note: It doesn’t matter where you are modifying the collection. If a collection is modified while you are enumerating its members, you get exception.

foreach Loop

You use C# foreach loop to iterate through a Dictionary<TKey, TValue>. Each item returned is a KeyValuePair<TKey, TValue> object, which contains a copy of the key and value elements of an item in the Dictionary<TKey, TValue> collection. You can access each element through the Key and Value property.

Note: The foreach statement only allows reading from, not writing to, the collection.

foreach (var planet in planets)
    Console.WriteLine($"{planet.Key}, {planet.Value}");

Run Demo

OUTPUT

1, Mercury
2, Venus
3, Earth

You cannot use the iteration to modify the contents of the collection. Any attempt to do that will result an exception of type InvalidOperationException with the message ‘Collection was modified; enumeration operation may not execute.’

foreach (var planet in planets)
{
    if (planet.Key == 2)
        planets.Remove(planet.Key); // Throw an exception here
}

Solution

Copy the keys in a temp list (or another collection) and then iterate through this temp list to modify the collection:

//Populate all the keys in a temp list
var keys = new List(planets.Keys); // Populated with 1, 2, 3

// Iterate through keys and remove the item from the collection (planets)
foreach (var key in keys)
{
    if (key == 2)
        planets.Remove(key); // Removed { 2, Venus }

    if (planets.ContainsKey(key))
        Console.WriteLine($"{key}, {planets[key]}");
}

Run Demo

OUTPUT

1, Mercury
3, Earth


Processing C# Dictionary with LINQ

You can use LINQ to process dictionary collection.

var planets = new Dictionary<int, string>()
{
    [1] = "Mercury",
    [2] = "Venus",
    [3] = "Earth"
};
// Namespace required
using System.Linq;
// LINQ Method Expression
var planet = planets.Where(p => p.Key == 2).SingleOrDefault();
Console.WriteLine($"{planet.Key}, {planet.Value}");

// LINQ Query Expression
var planet = (from p in planets where p.Key == 3 select p).SingleOrDefault();
Console.WriteLine($"{planet.Key}, {planet.Value}");

Run Demo

OUTPUT

2, Venus
3, Earth


C# Dictionary Examples

This statement declares and initializes a dictionary of 3 objects. Once the list is created, you can add items to the list with an Add method.

var alphabet = new Dictionary<int, char>()
{
    [1] = 'A',
    [2] = 'B',
    [3] = 'C'
};

//Add() to add item
alphabet.Add(4, 'D');
alphabet.Add(5, 'E');

// Add item by Key indexer
alphabet[6] = 'F';
alphabet[7] = 'G';

// Update item value associated with key 7 from G to H
alphabet[7] = 'H';

foreach (var letter in alphabet)
    Console.WriteLine($"{letter.Key}, {letter.Value}");

//Reset items
alphabet = new Dictionary<int, char>()
{
    [1] = 'A',
    [2] = 'B',
    [3] = 'C',
    [4] = 'D',
    [5] = 'E',
    [6] = 'F',
    [7] = 'G'
};

//Count to get total items
Console.WriteLine(alphabet.Count); // Prints 7

//Keys, Values 
foreach (var key in alphabet.Keys)
    Console.WriteLine(key);

foreach (var value in alphabet.Values)
    Console.WriteLine(value);

//Get value by key indexer
Console.WriteLine(alphabet[1]); // Prints A   
Console.WriteLine(alphabet[5]); // Prints E   

// foreach loop
foreach (var letter in alphabet)
    Console.WriteLine($"{letter.Key}, {letter.Value}");

//ContainsValue(), ContainsKey()
Console.WriteLine(alphabet.ContainsValue('B')); // Prints True
Console.WriteLine(alphabet.ContainsKey(10)); // Prints False

// Remove()
alphabet.Remove(2); //By Key

foreach (var letter in alphabet)
    Console.WriteLine($"{letter.Key}, {letter.Value}");

//Clear() to remove all the items
alphabet.Clear();
Console.WriteLine(alphabet.Count); // Prints 0

Run Demo

Dictionary<int, string> Vegetables = new Dictionary<int, string>
{
    [1] = "Carrot",
    [2] = "Cucumber",
    [3] = "Tomato",
    [4] = "Onion",
    [5] = "Green Pepper"
};

var integerValues = new Dictionary<int, int>();
integerValues.Add(1, 10);
integerValues.Add(2, 20);
integerValues.Add(3, 30);

//Code that creates a dictionary to holds decimal values
Dictionary<int,decimal> decimalValues = new Dictionary<int,decimal>();
decimalValues[1] = 13.2m;
decimalValues[2] = 20.74m;
decimalValues[3] = 8.34m;

Run Demo


C# Reference | Microsoft Docs