Site

Dictionary — C# Dictionary<K,V>

Tutorial S3  •  C# / Learn

S3.0 What This Teaches

This tutorial covers Dictionary<TKey, TValue>, C#'s hash map:

S3.1 Creating and Initializing

// Empty dictionary
var ages = new Dictionary<string, int>();

// Collection initializer
var capitals = new Dictionary<string, string>
{
    ["France"]  = "Paris",
    ["Germany"] = "Berlin",
    ["Japan"]   = "Tokyo"
};

// Infer types with var
var freq = new Dictionary<char, int>();

S3.2 Adding and Updating

var d = new Dictionary<string, int>();

d["Alice"] = 30;    // add or update
d.Add("Bob", 25);   // throws if key exists

// Increment a counter safely
string key = "cat";
d[key] = d.GetValueOrDefault(key, 0) + 1;

// Remove
d.Remove("Bob");
d.Clear();

S3.3 Safe Lookup

var d = new Dictionary<string, int> { ["a"] = 1, ["b"] = 2 };

// Direct indexer - throws KeyNotFoundException if missing
int val = d["a"];

// TryGetValue - preferred for uncertain lookups
if (d.TryGetValue("c", out int found))
    Console.WriteLine(found);
else
    Console.WriteLine("not found");

// GetValueOrDefault - returns default(T) or specified fallback
int v = d.GetValueOrDefault("x", -1);   // -1

// ContainsKey - use before indexer when you're sure key is present
bool exists = d.ContainsKey("b");   // True

S3.4 Iterating

var capitals = new Dictionary<string, string>
{
    ["France"] = "Paris", ["Germany"] = "Berlin", ["Japan"] = "Tokyo"
};

// Key-value pairs (order not guaranteed for Dictionary)
foreach (var (country, capital) in capitals)
    Console.WriteLine($"{country}: {capital}");

// Keys or values only
foreach (string country in capitals.Keys)
    Console.WriteLine(country);

foreach (string capital in capitals.Values)
    Console.WriteLine(capital);

// Count
Console.WriteLine(capitals.Count);  // 3

S3.5 Related Types

TypeOrdered?Use when
Dictionary<K,V>NoGeneral-purpose hash map; O(1) lookup
SortedDictionary<K,V>Yes (by key)Need keys in sorted order; O(log n) lookup
ConcurrentDictionary<K,V>NoThread-safe updates without explicit locks
ImmutableDictionary<K,V>NoSnapshot that cannot be modified
// ConcurrentDictionary: atomic GetOrAdd
using System.Collections.Concurrent;
var cd = new ConcurrentDictionary<string, int>();
cd.AddOrUpdate("hits", 1, (_, old) => old + 1);

S3.6 Example - All Together

// Dictionary - word frequency counter and inversion.

string text = "the quick brown fox jumps over the lazy dog the fox";
var freq = new Dictionary<string, int>();

foreach (string word in text.Split(' '))
    freq[word] = freq.GetValueOrDefault(word, 0) + 1;

// Sort by frequency descending
var top = freq.OrderByDescending(kv => kv.Value).Take(3);
foreach (var (word, count) in top)
    Console.WriteLine($"{word}: {count}");

// Invert: group words by their frequency
var byFreq = freq.GroupBy(kv => kv.Value)
                 .ToDictionary(g => g.Key, g => g.Select(kv => kv.Key).ToList());
foreach (var (count, words) in byFreq.OrderByDescending(kv => kv.Key))
    Console.WriteLine($"{count}: [{string.Join(", ", words)}]");

S3.7 Exercise

Exercise
  • Count character frequencies in a string using a Dictionary<char, int>. Print the five most frequent characters sorted by count descending.
  • Build a Dictionary<string, List<string>> that groups words by their first letter. Populate it from a word list.
  • Use TryGetValue to safely look up several keys, including some that don't exist, and print a "not found" message for missing ones.

S3.8 Common Mistakes

Using d["key"] when the key might not exist

int count = d["missing"];   // KeyNotFoundException
// Use TryGetValue or GetValueOrDefault instead

Using Add when you want to overwrite

d.Add("key", 1);   // OK
d.Add("key", 2);   // ArgumentException: key already exists
d["key"] = 2;      // always works - add or update

Assuming insertion order is preserved

Dictionary<K,V> does not guarantee insertion order. Use SortedDictionary for key-sorted order, or a List<KeyValuePair<K,V>> when order matters.

S3.9 Key Terms

TermMeaning
Dictionary<K,V>Hash map mapping unique keys to values; O(1) average lookup
TryGetValueReturns false instead of throwing when a key is missing
GetValueOrDefaultReturns a fallback value when a key is missing
ContainsKeyTests whether a key exists without retrieving the value
KeyValuePairThe element type when iterating a dictionary; has .Key and .Value
SortedDictionaryDictionary that keeps keys in sorted order; O(log n) operations