S3.0 What This Teaches
This tutorial covers Dictionary<TKey, TValue>, C#'s hash map:
- Creating and initializing dictionaries
- Adding, updating, and removing entries
- Safe lookup with
TryGetValue and GetValueOrDefault
- Iterating keys, values, and key-value pairs
- Related types:
SortedDictionary, ConcurrentDictionary
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
| Type | Ordered? | Use when |
Dictionary<K,V> | No | General-purpose hash map; O(1) lookup |
SortedDictionary<K,V> | Yes (by key) | Need keys in sorted order; O(log n) lookup |
ConcurrentDictionary<K,V> | No | Thread-safe updates without explicit locks |
ImmutableDictionary<K,V> | No | Snapshot 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
| Term | Meaning |
| Dictionary<K,V> | Hash map mapping unique keys to values; O(1) average lookup |
| TryGetValue | Returns false instead of throwing when a key is missing |
| GetValueOrDefault | Returns a fallback value when a key is missing |
| ContainsKey | Tests whether a key exists without retrieving the value |
| KeyValuePair | The element type when iterating a dictionary; has .Key and .Value |
| SortedDictionary | Dictionary that keeps keys in sorted order; O(log n) operations |