Dictionaries in C#
A Dictionary<TKey, TValue> stores values under unique keys, so you can look one up by its label instead of its position.
Apprentice · C# · Updated
After this lesson you can
- Store and look up values by key in a Dictionary<TKey, TValue>
- Loop through a dictionary's keys and values
Key takeaways
- A dictionary stores values under keys, so you look a value up by its key, as in
prices["bagel"], instead of by its position. - Each key appears only once: setting a key that's already there replaces its value, while
Addstops the program with anArgumentException. - Reading a key that isn't there stops the program with a
KeyNotFoundException, so check withContainsKeyor useTryGetValue. foreachgives each pair as aKeyValuePairwith a.Keyand a.Value;.Keysand.Valuesloop over just one side.- A dictionary doesn't promise any order. When you need the keys in order, use a
SortedDictionary<TKey, TValue>, which keeps them sorted.
A list finds items by their position: the first, the third. Often you want to find something by a label instead: the price of "coffee", the mascot of "Georgia", the phone number of "Ana". A dictionary stores values in key/value pairs: the key is the label, and the value is what it labels.
Creating a dictionary
The two types in angle brackets are the key's type and the value's type:
Dictionary<string, decimal> prices = new Dictionary<string, decimal>();
prices["coffee"] = 3.50m;
prices["bagel"] = 2.25m;
prices["juice"] = 4.00m;
Console.WriteLine(prices["bagel"]);
Console.WriteLine(prices.Count);
2.25
3
Dictionary<string, decimal> reads as "a dictionary from strings to decimals". You set and read values with the key in square brackets, where a list would take an index.
You can also fill it as you create it:
Dictionary<string, string> mascots = new Dictionary<string, string>
{
["Georgia"] = "Bulldogs",
["Alabama"] = "Crimson Tide",
["Ohio State"] = "Buckeyes"
};
Console.WriteLine(mascots["Ohio State"]);
Buckeyes
Keys are unique
Each key appears at most once, like a word in a real dictionary. Setting a key that's already there replaces its value:
Dictionary<string, decimal> prices = new Dictionary<string, decimal>();
prices["coffee"] = 3.50m;
prices["coffee"] = 3.75m;
Console.WriteLine( quot;{prices.Count} item, coffee costs {prices["coffee"]}");
1 item, coffee costs 3.75
Add(key, value) also adds a pair, but it stops the program with an ArgumentException if the key is already there. Use it when a repeated key would be a mistake.
Looking up safely
Reading a key that isn't in the dictionary stops the program with a KeyNotFoundException. Check first with ContainsKey, or use TryGetValue, which does the check and the lookup in one go:
Dictionary<string, decimal> prices = new Dictionary<string, decimal>
{
["coffee"] = 3.50m,
["bagel"] = 2.25m
};
Console.WriteLine(prices.ContainsKey("tea"));
if (prices.TryGetValue("bagel", out decimal price))
{
Console.WriteLine( quot;A bagel is {price:C}");
}
if (!prices.TryGetValue("tea", out decimal teaPrice))
{
Console.WriteLine("We don't sell tea.");
}
False
A bagel is $2.25
We don't sell tea.
TryGetValue returns true and fills the out variable when the key is there, the same shape as int.TryParse.
Removing
Remove(key) takes a pair out, and returns true if the key was there:
Dictionary<string, int> stock = new Dictionary<string, int> { ["apples"] = 12, ["pears"] = 0 };
stock.Remove("pears");
Console.WriteLine(stock.Count);
1
Looping through a dictionary
foreach visits every pair. Each one is a KeyValuePair, with a .Key and a .Value:
Dictionary<string, int> wins = new Dictionary<string, int>
{
["Georgia"] = 12,
["Alabama"] = 10,
["Ohio State"] = 11
};
foreach (KeyValuePair<string, int> team in wins)
{
Console.WriteLine( quot;{team.Key}: {team.Value}");
}
int totalWins = 0;
foreach (int teamWins in wins.Values)
{
totalWins += teamWins;
}
Console.WriteLine( quot;Total: {totalWins}");
Georgia: 12
Alabama: 10
Ohio State: 11
Total: 33
wins.Keys and wins.Values let you loop over just the keys or just the values.
A dictionary doesn't promise any order. Pairs often come out in the order they were added, but don't count on it. When the order matters, use a SortedDictionary<TKey, TValue>, which keeps its keys sorted.
Counting with a dictionary
A classic use: count how many times each thing appears.
string[] votes = { "pizza", "tacos", "pizza", "sushi", "pizza", "tacos" };
Dictionary<string, int> counts = new Dictionary<string, int>();
foreach (string vote in votes)
{
if (counts.ContainsKey(vote))
{
counts[vote]++;
}
else
{
counts[vote] = 1;
}
}
Console.WriteLine( quot;pizza: {counts["pizza"]}, tacos: {counts["tacos"]}, sushi: {counts["sushi"]}");
pizza: 3, tacos: 2, sushi: 1
Check yourself
2 questions to try on the lesson page.
So what
Whenever you find yourself searching a list for "the one with this name", a dictionary is the better tool: it goes straight to the value by its key.