Codectionary / Developer documentation / C#

Dictionary<TKey, TValue>

Dictionary<TKey, TValue> stores data as key-value pairs, offering fast average-case lookup, insertion, and deletion by key, backed by a hash table. Keys must be unique - adding a value with an existing key throws an exception, while indexer assignment (dict[key] = value) overwrites it instead. Dictionary does not guarantee any particular iteration order.

Read the syntax

Dictionary<TKey,TValue> associates unique keys with values. Add rejects an existing key, while the indexer can add or replace a value and throws when reading a missing key.

ContainsKey or TryGetValue checks an uncertain key safely. foreach visits key/value pairs; use a lookup by key rather than relying on iteration order for program logic.

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("John", 21);
ages["Zain"] = 22;   // indexer syntax also works for adding
ages["Jamal"] = 20;

Console.WriteLine(ages["Zain"]);  // 22
Console.WriteLine(ages.Count);     // 3
  1. Building a Dictionary and adding key-value pairs.
  2. Dictionary<TKey,TValue> associates unique keys with values. Add rejects an existing key, while the indexer can add or replace a value and throws when reading a missing key.
  3. Add and indexer assignments create three entries. Looking up Zain prints 22 and Count prints 3.

Checking, 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");
  1. Common operations for working with dictionary entries.
  2. Dictionary<TKey,TValue> associates unique keys with values. Add rejects an existing key, while the indexer can add or replace a value and throws when reading a missing key.
  3. ContainsKey finds apples. TryGetValue fails for mango, so the else message prints; the final assignments update apples and 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}");
}
  1. Looping through keys, values, or both together.
  2. Dictionary<TKey,TValue> associates unique keys with values. Add rejects an existing key, while the indexer can add or replace a value and throws when reading a missing key.
  3. Each foreach loop visits the same two pairs, once through KeyValuePair properties and once through deconstruction. Do not use their traversal order as a business rule.

Dictionary with Object Values

A very common pattern: grouping related data under a dictionary of complex objects.

Dictionary<string, Student> students = new Dictionary<string, Student>
{
    ["s1"] = new Student("John", 85),
    ["s2"] = new Student("Zain", 92)
};

Console.WriteLine(students["s1"].Name);  // John

record Student(string Name, int Grade);
  1. A very common pattern: grouping related data under a dictionary of complex objects.
  2. Dictionary<TKey,TValue> associates unique keys with values. Add rejects an existing key, while the indexer can add or replace a value and throws when reading a missing key.
  3. Each key maps to a Student record rather than a simple number. The s1 lookup returns the first record, and its Name prints John.

Best 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

Runtime & versions

.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

C# language reference

Specifications & further reading