Iterating through dictionary with ForEach
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
In C#, iterating a dictionary is usually simple, but there is recurring confusion about foreach versus a hypothetical ForEach method. Dictionary<TKey, TValue> does not expose a built-in .ForEach(...) helper the way List<T> does, so the idiomatic approach is a normal foreach loop over key-value pairs. The important part is understanding what the loop yields, how to access keys and values cleanly, and what changes are safe during enumeration.
Use foreach as the Default Pattern
A dictionary enumerates KeyValuePair<TKey, TValue> entries. That means each loop variable contains both the key and the value:
This is the most direct and readable approach. In business code, it is usually better than forcing a chained LINQ style just to avoid a loop.
Modern C# also supports deconstruction:
Use whichever form your codebase finds clearer.
Iterate Keys or Values Only When That Is All You Need
If the loop needs only keys or only values, iterate the dedicated collection instead of ignoring half the pair:
This communicates intent better and avoids unused variables. It also makes review easier because the reader can see immediately whether the key, the value, or both are relevant.
Understand Ordering and Determinism
Many developers assume dictionary traversal is naturally sorted. That is not the contract. If you need deterministic output by key, sort explicitly:
If sorted iteration is your normal access pattern, a SortedDictionary<TKey, TValue> may be a better fit than repeatedly ordering a plain dictionary at call sites.
The key point is to choose a data structure that matches your required semantics instead of depending on incidental iteration behavior.
Do Not Modify Structure While Iterating
You can read dictionary entries safely during enumeration, but adding or removing keys while the loop is active will throw at runtime.
This is unsafe:
The safe pattern is a two-pass approach:
The same principle applies if you need to add new entries. Collect the change set first, then apply it after enumeration ends.
Avoid Fake ForEach Patterns
Because Dictionary<TKey, TValue> has no built-in .ForEach, some code converts the dictionary to a list only to call List<T>.ForEach. That usually makes the code worse:
This allocates an extra list and hides a straightforward loop behind an unnecessary transformation. Unless you have a very specific reason, prefer the ordinary foreach.
If you really want a reusable helper, write an extension method explicitly and use it sparingly:
Even then, a plain foreach is often clearer.
Thread Safety Matters
A normal Dictionary<TKey, TValue> is not safe for concurrent mutation. If one thread is iterating while another modifies the dictionary, you can get exceptions or inconsistent behavior.
For shared mutable state, use ConcurrentDictionary<TKey, TValue> and still think carefully about your consistency rules. Safe enumeration at the collection level does not automatically guarantee correct business behavior.
Common Pitfalls
- Assuming a dictionary has a built-in
.ForEachmethod likeList<T>. - Modifying keys during
foreachenumeration and hitting runtime exceptions. - Depending on iteration order when sorted output was actually required.
- Converting to a list just to call
.ForEach, which adds allocation and obscures intent. - Ignoring thread-safety concerns when a dictionary is shared across threads.
Summary
- In C#, the idiomatic way to iterate a dictionary is a normal
foreachloop. - Dictionary enumeration yields key-value pairs, and deconstruction is available for readability.
- Iterate
KeysorValuesdirectly when only one side is needed. - Do structural updates after the loop, not during it.
- Prefer explicit loops over artificial
ForEachwrappers unless a helper clearly improves the codebase.
Related reading
- Iterative deepening vs depth-first search
- Iterative depth-first tree traversal with pre- and post-visit at each node
- Iterative DFS vs Recursive DFS and different elements order
- Iteratively compute the Cartesian product of an arbitrary number of sets
- Iteration order of HashSet
- Java8 HashMap<X, Y> to HashMap<X, Z> using Stream / Map-Reduce / Collector
- Java - Sort one array based on values of another array?
- java codility Max-Counters

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.