Question
In C#, I have seen several different ways to iterate over a dictionary. Is there a standard or recommended way to do it?
For example, given a dictionary like this:
var scores = new Dictionary<string, int>
{
{ "Alice", 95 },
{ "Bob", 87 },
{ "Charlie", 91 }
};
What is the usual way to loop through its contents, and when should I iterate over key-value pairs instead of only keys or only values?
Short Answer
By the end of this page, you will understand the standard way to iterate over a Dictionary<TKey, TValue> in C#, how to access keys and values, when to use foreach with KeyValuePair, and which common patterns developers use in real projects.
Concept
A dictionary in C# stores data as key-value pairs. Each key is unique, and each key maps to one value.
When you iterate over a dictionary, the most common goal is one of these:
- read both the key and the value
- read only the keys
- read only the values
The standard way to iterate over a dictionary is with foreach. A Dictionary<TKey, TValue> is enumerable, so you can loop through it directly.
When you do that, each item is a KeyValuePair<TKey, TValue>. That means each loop iteration gives you:
item.Keyitem.Value
Example:
foreach (KeyValuePair<string, int> item in scores)
{
Console.WriteLine($"{item.Key}: {item.Value}");
}
In modern C#, var is also common:
foreach (var item in scores)
{
Console.WriteLine($"{item.Key}: {item.Value}");
}
Mental Model
Think of a dictionary like a set of labeled drawers.
- The key is the label on the drawer.
- The value is what is stored inside.
When you iterate over the whole dictionary, you walk past each drawer and see both the label and the contents.
When you iterate over .Keys, you only read the labels.
When you iterate over .Values, you only inspect the contents.
So the question is simple: what information do you need while looping?
- Need both label and content? Loop through the dictionary.
- Need only labels? Loop through
Keys. - Need only contents? Loop through
Values.
That is the mental shortcut most developers use.
Syntax and Examples
Standard way: iterate over key-value pairs
var scores = new Dictionary<string, int>
{
{ "Alice", 95 },
{ "Bob", 87 },
{ "Charlie", 91 }
};
foreach (var pair in scores)
{
Console.WriteLine($"{pair.Key} => {pair.Value}");
}
This is the most common and recommended approach when you need both the key and the value.
Iterate over only keys
foreach (var key in scores.Keys)
{
Console.WriteLine(key);
}
Use this when only the keys matter.
Iterate over only values
foreach (var value in scores.Values)
{
Console.WriteLine(value);
}
Use this when only the values matter.
Deconstruction syntax
In modern C#, you can deconstruct key-value pairs:
Step by Step Execution
Consider this code:
var scores = new Dictionary<string, int>
{
{ "Alice", 95 },
{ "Bob", 87 }
};
foreach (var pair in scores)
{
Console.WriteLine($"{pair.Key}: {pair.Value}");
}
Step by step:
- A dictionary named
scoresis created. - It contains two entries:
- key
"Alice"with value95 - key
"Bob"with value87
- key
- The
foreachloop starts. - On the first iteration,
pairrepresents one key-value pair, for example:pair.Keyis"Alice"pair.Valueis95
Real World Use Cases
Configuration settings
var settings = new Dictionary<string, string>
{
{ "Theme", "Dark" },
{ "Language", "en-US" },
{ "Region", "US" }
};
foreach (var (key, value) in settings)
{
Console.WriteLine($"{key} = {value}");
}
Useful for printing, validating, or exporting app settings.
Counting occurrences
var wordCounts = new Dictionary<string, int>
{
{ "apple", 3 },
{ "banana", 5 }
};
foreach (var (word, count) in wordCounts)
{
Console.WriteLine($"{word} appears {count} times");
}
Common in text analysis and reporting.
API or JSON-like field processing
Some applications map field names to values for dynamic processing.
Real Codebase Usage
In real codebases, developers usually choose the loop style based on what they need.
Common pattern: iterate over the whole dictionary
Use this when you need both key and value.
foreach (var (userId, userName) in users)
{
logger.LogInformation($"User {userId}: {userName}");
}
Common pattern: validation
foreach (var (field, value) in formData)
{
if (string.IsNullOrWhiteSpace(value))
{
Console.WriteLine($"Missing value for {field}");
}
}
This is common in request validation and data cleaning.
Common pattern: guard clause before lookup or processing
if (scores.Count == 0)
{
return;
}
foreach (var (name, score) in scores)
{
Console.WriteLine($"{name}: {score}");
}
Common pattern: use TryGetValue instead of iterating for one key
Common Mistakes
1. Iterating over keys when you really need both key and value
Broken or less clear approach:
foreach (var key in scores.Keys)
{
Console.WriteLine($"{key}: {scores[key]}");
}
This works, but if you need both key and value, iterating over the dictionary directly is clearer.
Better:
foreach (var pair in scores)
{
Console.WriteLine($"{pair.Key}: {pair.Value}");
}
2. Expecting a guaranteed order
Beginners sometimes assume the items will always come out in a specific order.
foreach (var pair in scores)
{
Console.WriteLine(pair.Key);
}
Do not build logic that depends on order unless you use a collection type intended for ordered behavior.
3. Modifying the dictionary during foreach
Broken example:
foreach (var pair in scores)
{
(pair.Value < )
{
scores.Remove(pair.Key);
}
}
Comparisons
| Approach | Best when | Example | Notes |
|---|---|---|---|
foreach (var pair in dictionary) | You need both key and value | pair.Key, pair.Value | Standard and most common |
foreach (var key in dictionary.Keys) | You only need keys | key | Clear and direct |
foreach (var value in dictionary.Values) | You only need values | value | Best when keys are irrelevant |
foreach (var (key, value) in dictionary) | You need both, with cleaner syntax |
Cheat Sheet
Quick reference
Iterate over key-value pairs
foreach (var pair in dictionary)
{
Console.WriteLine(pair.Key);
Console.WriteLine(pair.Value);
}
Iterate over keys only
foreach (var key in dictionary.Keys)
{
Console.WriteLine(key);
}
Iterate over values only
foreach (var value in dictionary.Values)
{
Console.WriteLine(value);
}
Deconstruct pairs
foreach (var (key, value) in dictionary)
{
Console.WriteLine($"{key}: {value}");
}
Look up one key
if (dictionary.TryGetValue("someKey", out var value))
{
Console.WriteLine();
}
FAQ
Is foreach the standard way to iterate over a dictionary in C#?
Yes. foreach is the normal and recommended way to iterate over a Dictionary<TKey, TValue>.
What type do I get when I loop over a dictionary?
Each item is a KeyValuePair<TKey, TValue>, so you can access .Key and .Value.
Should I loop over Keys and then use dictionary[key]?
Only if you truly only need keys. If you need both key and value, iterating over the dictionary directly is usually clearer.
Can I use a for loop with a dictionary?
Not naturally. Dictionaries are not index-based collections, so foreach is the better fit.
Can I change the dictionary while looping through it?
Not safely with a normal foreach. Adding or removing entries during enumeration can cause an exception.
How do I get just one value from a dictionary?
Use TryGetValue instead of iterating through every item.
Is deconstruction a good way to iterate?
Mini Project
Description
Build a simple student score reporter using a C# dictionary. This project demonstrates the standard way to iterate over dictionary entries, print formatted output, and apply a small condition while looping.
It is useful because dictionaries are commonly used to map names, IDs, or codes to values in real applications.
Goal
Create a program that stores student scores in a dictionary, prints every student and score, and highlights students with scores of 90 or higher.
Requirements
- Create a
Dictionary<string, int>with at least four student scores. - Iterate over the dictionary using
foreach. - Print each student's name and score.
- Print a second message for students whose score is 90 or higher.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
C# Type Checking Explained: typeof vs GetType() vs is
Learn when to use typeof, GetType(), and is in C#. Understand exact type checks, inheritance, and safe type testing clearly.
C# Version Numbers Explained: C# vs .NET Framework and Why “C# 3.5” Is Incorrect
Learn the correct C# version numbers, how they map to .NET releases, and why terms like C# 3.5 are inaccurate and confusing.