Syntax
Dictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>();Examples
Creating and Adding Entries
Building a Dictionary and adding key-value pairs.
Dictionary<string, int> ages = new Dictionary<string, int>();
ages.Add("Fola", 21);
ages["Zain"] = 22; // indexer syntax also works for adding
ages["Jamal"] = 20;
Console.WriteLine(ages["Zain"]); // 22
Console.WriteLine(ages.Count); // 3Checking, Updating, and Removing
Common operations for working with dictionary entries.
Dictionary<string, int> stock = new Dictionary<string, int>
{
["apples"] = 50,
["bananas"] = 30
};
Console.WriteLine(stock.ContainsKey("apples")); // true
if (stock.TryGetValue("mango", out int count))
{
Console.WriteLine(count);
}
else
{
Console.WriteLine("mango not in stock");
}
stock["apples"] = 45; // overwrites the existing value
stock.Remove("bananas");Iterating Over a Dictionary
Looping through keys, values, or both together.
Dictionary<string, int> scores = new Dictionary<string, int>
{
["Alice"] = 85,
["Bob"] = 92
};
foreach (KeyValuePair<string, int> entry in scores)
{
Console.WriteLine($"{entry.Key}: {entry.Value}");
}
// Deconstruction syntax is also available
foreach (var (name, score) in scores)
{
Console.WriteLine($"{name} -> {score}");
}Dictionary with Object Values
A very common pattern: grouping related data under a dictionary of complex objects.
record Student(string Name, int Grade);
Dictionary<string, Student> students = new Dictionary<string, Student>
{
["s1"] = new Student("Fola", 85),
["s2"] = new Student("Zain", 92)
};
Console.WriteLine(students["s1"].Name); // FolaBest practices
- Use TryGetValue() instead of checking ContainsKey() and then indexing separately, for cleaner and more efficient lookups
- Use the indexer (dict[key] = value) for add-or-update semantics, and .Add() only when you specifically want an exception on a duplicate key
- Choose a SortedDictionary<TKey,TValue> instead if you need keys kept in sorted order, since Dictionary makes no ordering guarantee
- Always override Equals() and GetHashCode() properly (or use a record) for any custom class you use as a dictionary key
At a glance
- Purpose
- Applications on the .NET platform
- File extension
- .cs
- Runs in
- .NET runtime
- Usually used with
- .NET SDK and libraries
Specifications & further reading
Related C# documentation
List<T>
List<T> is a resizable, generic collection from System.Collections.Generic, and the most commonly used collection type in C#. Unlike a plain array, a List<T> automatically grows as elements are added, and it provides a rich set of methods for adding, removing, searching, and sorting. The <T> means a List can be strongly typed to hold any specific type, like List<string> or List<int>.Queue<T> & Stack<T>
Queue<T> is a first-in-first-out (FIFO) collection - items are added with Enqueue() and removed with Dequeue(), just like a real-world line. Stack<T> is last-in-first-out (LIFO) - items are added with Push() and removed with Pop(), like a stack of plates. Both are useful for specific processing orders where a general-purpose List<T> would require extra bookkeeping.HashSet<T>
HashSet<T> is a collection that stores unique elements with no guaranteed ordering, backed by a hash table. Adding a duplicate element has no effect, since HashSet automatically enforces uniqueness. It provides very fast average-case performance for adding, removing, and checking membership, and offers built-in set operations like union, intersection, and difference.foreach & IEnumerable
foreach is C#'s dedicated loop for iterating over any collection that implements IEnumerable<T> - which includes arrays, List<T>, Dictionary<TKey,TValue>, and virtually every built-in collection. Behind the scenes, foreach uses an enumerator (via GetEnumerator()) to walk through items one at a time. Any custom class can support foreach by implementing IEnumerable<T> itself.
List<T> is a resizable, generic collection from System.Collections.Generic, and the most commonly used collection type in C#. Unlike a plain array, a List<T> automatically grows as elements are added, and it provides a rich set of methods for adding, removing, searching, and sorting. The <T> means a List can be strongly typed to hold any specific type, like List<string> or List<int>.Queue<T> & Stack<T>
Queue<T> is a first-in-first-out (FIFO) collection - items are added with Enqueue() and removed with Dequeue(), just like a real-world line. Stack<T> is last-in-first-out (LIFO) - items are added with Push() and removed with Pop(), like a stack of plates. Both are useful for specific processing orders where a general-purpose List<T> would require extra bookkeeping.HashSet<T>
HashSet<T> is a collection that stores unique elements with no guaranteed ordering, backed by a hash table. Adding a duplicate element has no effect, since HashSet automatically enforces uniqueness. It provides very fast average-case performance for adding, removing, and checking membership, and offers built-in set operations like union, intersection, and difference.foreach & IEnumerable
foreach is C#'s dedicated loop for iterating over any collection that implements IEnumerable<T> - which includes arrays, List<T>, Dictionary<TKey,TValue>, and virtually every built-in collection. Behind the scenes, foreach uses an enumerator (via GetEnumerator()) to walk through items one at a time. Any custom class can support foreach by implementing IEnumerable<T> itself.