What a dictionary is
A dictionary stores key-value pairs. Each key maps to one value, and you look a value up by its key rather than by a numeric position. This is the natural fit when the data is "a name and its score", "a word and its count" or "an id and its record". In other languages the same idea is called a hash map, an object or a map.
In C# it is Dictionary<TKey, TValue>, which lives in System.Collections.Generic. There is nothing to install and no extra import beyond that namespace, which most projects already include.
Creating one and adding entries
The type arguments name the key type first and the value type second. Dictionary<string, int> maps strings to integers:
Dictionary<string, int> ages = new Dictionary<string, int>();
ages["Alice"] = 25;
ages["Bob"] = 30;
Console.WriteLine(ages["Alice"]); // 25
Console.WriteLine(ages.Count); // 2
The square-bracket syntax is the indexer. Assigning through it adds the key when it is missing and overwrites the value when the key already exists. There is no separate "put" method in C#.
You can also fill a dictionary when you create it, with an initializer:
var scores = new Dictionary<string, int> {
["Alice"] = 95,
["Bob"] = 87
};
Add versus the indexer
Dictionaries also have an Add(key, value) method. The difference matters: Add throws an ArgumentException when the key is already present, while the indexer quietly replaces the old value.
var d = new Dictionary<string, int>();
d.Add("Alice", 1); // fine
d["Alice"] = 2; // fine, replaces 1 with 2
d.Add("Alice", 3); // throws ArgumentException
Use Add when a duplicate would be a bug you want to hear about, and the indexer when you want "set this key to this value" without caring whether it existed.
Rules worth knowing
- Keys are unique. A dictionary holds at most one value per key. Values can repeat.
- Keys are compared by content for strings.
"Alice"and a different string object holding the same letters are the same key. Case counts, so"alice"is a different key. - A key can't be
null. Usingnullas a key throws an exception. - Don't rely on order. A dictionary is built for fast lookup by key. Treat its enumeration order as unspecified.
- Lookup is fast. Finding, adding or replacing a key takes constant time on average.
Looping over a dictionary
A foreach loop over a dictionary gives you one KeyValuePair per entry, with Key and Value properties:
foreach (var pair in ages) {
Console.WriteLine(pair.Key + " is " + pair.Value);
}
// Alice is 25
// Bob is 30
Entries come out in insertion order here only because nothing was removed. Don't write code that depends on that. Also avoid changing the dictionary's entries inside the loop: adding a new key while enumerating throws an InvalidOperationException.
The exercise, step by step
The task is to create a dictionary named scores with three student scores.
- Declare the dictionary. Write
Dictionary<string, int> scores = new Dictionary<string, int>();. The keys are student names (strings) and the values are scores (integers). - Add three entries through the indexer.
"Alice"gets 95,"Bob"gets 87 and"Charlie"gets 72.
Dictionary<string, int> scores = new Dictionary<string, int>();
scores["Alice"] = 95;
scores["Bob"] = 87;
scores["Charlie"] = 72;
After these lines, scores.Count is 3.
Common mistakes
- Using another language's names. A C# dictionary is
Dictionary, notHashMap. The type arguments use C# type names:stringandint, notStringandInteger. Code ported from Java often usesput(...)andnew HashMap<>(), and neither exists in C#. - Forgetting the type arguments.
new Dictionary()without<string, int>doesn't compile for the generic type. - Calling
Addtwice with the same key. The second call throws. - Putting the key and value types in the wrong order.
Dictionary<int, string>would make scores the keys, andscores["Alice"]would no longer compile. - Wrong string quotes. Keys are string literals in double quotes. Single quotes make a
char, which is a different type.
Key takeaways
Dictionary<TKey, TValue>maps unique keys to values.d[key] = valueadds or replaces.d.Add(key, value)throws on a duplicate key.Countgives the number of entries.- Don't depend on the order of entries.