C# Dictionary
A Dictionary<TKey, TValue> stores data as key-value pairs. Each key is unique, and you use it to look up its associated value — like looking up a word in a real dictionary to find its meaning.
The Key-Value Concept
┌──────────────────────────────────────────────────────────────┐ │ DICTIONARY — KEY-VALUE PAIRS │ ├───────────────────────┬──────────────────────────────────────┤ │ Key │ Value │ ├───────────────────────┼──────────────────────────────────────┤ │ "Name" │ "Alice" │ │ "Age" │ 30 │ │ "Country" │ "India" │ ├───────────────────────┼──────────────────────────────────────┤ │ Keys must be unique │ Values can repeat │ │ Like an index │ Like a lookup result │ └───────────────────────┴──────────────────────────────────────┘ Real-world analogy: A phone book Name (key) → Phone Number (value) "Alice" → "555-1234" "Bob" → "555-5678"
Creating a Dictionary
using System;
using System.Collections.Generic;
// Empty dictionary: string keys, int values
Dictionary<string, int> ages = new Dictionary<string, int>();
// Dictionary with initial values:
Dictionary<string, string> capitals = new Dictionary<string, string>()
{
{ "France", "Paris" },
{ "Germany", "Berlin" },
{ "Japan", "Tokyo" }
};
Adding and Updating Items
Dictionary<string, int> scores = new Dictionary<string, int>();
// Add new entries:
scores.Add("Alice", 90);
scores.Add("Bob", 75);
scores.Add("Carol", 88);
// Update existing entry:
scores["Alice"] = 95; // overwrite Alice's score
// Add or update using indexer (safe):
scores["Dave"] = 82; // adds Dave if not present, updates if present
Dictionary Add Diagram
┌──────────────────────────────────────────────────────────────┐
│ DICTIONARY INTERNAL STRUCTURE │
├────────────────┬─────────────────────────────────────────────┤
│ Hash of Key │ Bucket → Key-Value Pair │
├────────────────┼─────────────────────────────────────────────┤
│ hash("Alice") │ "Alice" → 90 │
│ hash("Bob") │ "Bob" → 75 │
│ hash("Carol") │ "Carol" → 88 │
└────────────────┴─────────────────────────────────────────────┘
Lookup is O(1) — instant access by key (no scanning)
Accessing Values
Dictionary<string, string> capitals = new Dictionary<string, string>()
{
{ "France", "Paris" },
{ "Japan", "Tokyo" }
};
// Direct access (throws exception if key missing):
Console.WriteLine(capitals["France"]); // Paris
// Safe access with TryGetValue:
if (capitals.TryGetValue("Japan", out string capital))
{
Console.WriteLine(capital); // Tokyo
}
// Check if key exists before accessing:
if (capitals.ContainsKey("Germany"))
{
Console.WriteLine(capitals["Germany"]);
}
else
{
Console.WriteLine("Germany not found.");
}
Removing Items
scores.Remove("Bob"); // removes the "Bob" entry
Console.WriteLine(scores.ContainsKey("Bob")); // False
Iterating Through a Dictionary
Dictionary<string, int> prices = new Dictionary<string, int>()
{
{ "Apple", 50 },
{ "Mango", 80 },
{ "Banana", 30 }
};
// Loop through all key-value pairs:
foreach (KeyValuePair<string, int> item in prices)
{
Console.WriteLine(item.Key + " costs " + item.Value);
}
// Output:
// Apple costs 50
// Mango costs 80
// Banana costs 30
// Loop through keys only:
foreach (string key in prices.Keys)
{
Console.WriteLine(key);
}
// Loop through values only:
foreach (int price in prices.Values)
{
Console.WriteLine(price);
}
Common Properties and Methods
Dictionary<string, int> d = new Dictionary<string, int>()
{
{ "A", 1 }, { "B", 2 }, { "C", 3 }
};
Console.WriteLine(d.Count); // 3
Console.WriteLine(d.ContainsKey("B")); // True
Console.WriteLine(d.ContainsValue(3)); // True
d.Remove("A");
Console.WriteLine(d.Count); // 2
d.Clear();
Console.WriteLine(d.Count); // 0
Real Example: Word Frequency Counter
using System;
using System.Collections.Generic;
string[] words = { "cat", "dog", "cat", "bird", "dog", "cat" };
Dictionary<string, int> frequency = new Dictionary<string, int>();
foreach (string word in words)
{
if (frequency.ContainsKey(word))
frequency[word]++; // increment count
else
frequency[word] = 1; // first occurrence
}
foreach (KeyValuePair<string, int> entry in frequency)
{
Console.WriteLine(entry.Key + ": " + entry.Value + " times");
}
// Output:
// cat: 3 times
// dog: 2 times
// bird: 1 times
Word Counter Flow Diagram
┌────────────────────────────────────────────────────────────┐
│ Input: ["cat","dog","cat","bird","dog","cat"] │
├────────────────────────────────────────────────────────────┤
│ │
│ Process "cat" → {"cat": 1} │
│ Process "dog" → {"cat": 1, "dog": 1} │
│ Process "cat" → {"cat": 2, "dog": 1} │
│ Process "bird" → {"cat": 2, "dog": 1, "bird": 1} │
│ Process "dog" → {"cat": 2, "dog": 2, "bird": 1} │
│ Process "cat" → {"cat": 3, "dog": 2, "bird": 1} │
│ │
└────────────────────────────────────────────────────────────┘
Nested Dictionary
A dictionary can hold another dictionary as its value. This models hierarchical data like country → cities.
Dictionary<string, List<string>> countryCities = new Dictionary<string, List<string>>()
{
{ "India", new List<string>() { "Delhi", "Mumbai", "Chennai" } },
{ "USA", new List<string>() { "New York", "Los Angeles" } }
};
foreach (string city in countryCities["India"])
{
Console.WriteLine(city);
}
// Delhi, Mumbai, Chennai
Quick Reference
┌────────────────────────────┬────────────────────────────────┐ │ Method/Property │ What It Does │ ├────────────────────────────┼────────────────────────────────┤ │ Add(key, value) │ Add new key-value pair │ │ Remove(key) │ Remove entry by key │ │ ContainsKey(key) │ Check if key exists │ │ ContainsValue(val) │ Check if value exists │ │ TryGetValue(key, out val) │ Safe lookup — no exception │ │ Clear() │ Remove all entries │ │ Count │ Number of entries │ │ Keys │ Collection of all keys │ │ Values │ Collection of all values │ └────────────────────────────┴────────────────────────────────┘
Dictionary is the go-to collection when you need fast lookup by a unique key. It powers features like caching, user session data, configuration settings, and data aggregation. Knowing it well makes many real-world coding tasks significantly easier.
