LogIn
I don't have account.

How to iterate a Dictionary in C# ?

DevSniper

166 Views

When working with key–value pairs in C#, the Dictionary<TKey, TValue> is one of the most powerful and frequently used generic collections. However, a common question developers face is

How do I iterate through a Dictionary in C# efficiently and correctly?

In this article, we’ll explore all the practical and advanced ways to iterate through a Dictionary, understand what happens internally, learn about performance considerations and see real-world examples you can directly use in production code.

What is a Dictionary in C#?

A Dictionary in C# (defined in the System.Collections.Generic namespace) stores key–value pairs where each key must be unique and values can be duplicated. It provides O(1) average-time lookups, insertions and deletions thanks to its internal hash table implementation. Click here to learn Dictionary in depth

Internal Working of Dictionary

Internally, Dictionary<TKey, TValue> uses

  • Buckets : an array storing indices of entries.
  • Entries : an array of structures containing {hashCode, key, value, next}

Explore in depth of Internal Working of Dictionary

How to Iterate a Dictionary in C#?

In C# , Dictionary is unordered Data structure,which means that you cann't expect that the return values of a Dictionary will be in same order every time. So when you loop/iterate it more time it can print values in different order and order of values unpredictable.

There are several ways to iterate through a dictionary in C#, each suitable for different use cases.

1. Using foreach Loop : The Most Common and Readable Way

The foreach loop is the most straightforward and commonly used approach to iterate through all the key–value pairs in a dictionary. It’s clean, safe and works for all data types.

Copy
using System.IO;
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary < string,string> dict = new Dictionary<string,string> {
            {"language","C#"},
            {"topic","Dictionary"},
            {"label","Beginner"}
        };
        foreach(KeyValuePair<string,string> kvp in dict) {
            Console.WriteLine( $"Key : {kvp.Key} Value : {kvp.Value}");
        }
    }
}
Key : language Value : C#
Key : topic Value : Dictionary
Key : label Value : Beginner

What Happens Internally?

When you use foreach, the compiler uses the dictionary’s enumerator (via GetEnumerator()) under the hood. It iterates through the internal hash buckets where key–value pairs are stored.

This approach ensures that you don’t need to manage iteration manually and it handles all the complexity for you.

You can also deconstruct the key-value pair directly inside the foreach loop for cleaner code.

Copy
foreach (var (key, value) in dict)
{
    Console.WriteLine($"Key {key} Value : {value}");
}
OR
Copy
foreach(var item in dict) {
   Console.WriteLine($"item : {item} \n\t Key {item.Key} Value : {item.Value}");
}
Iterating Over Only Keys or Only Values

If you only need keys or values, it’s more efficient to iterate directly through .Keys or .Values.

It is helpful, in many real-world scenarios, Where you may only need to access keys or values from a Dictionary<TKey, TValue>, not both.

Copy
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary<string, string> dict = new()
        {
            { "language", "C#" },
            { "topic", "Dictionary" },
            { "level", "Beginner" }
        };
        Console.WriteLine("Keys:");
        foreach (var key in dict.Keys)
        {
            Console.WriteLine(key);
        } 
        Console.WriteLine("\nValues:");
        foreach (var value in dict.Values)
        {
            Console.WriteLine(value);
        }
    }
}
Keys:
language
topic
level

Values:
C#
Dictionary
Beginner
Pro Tips

Modifying the dictionary while iterating dictionary or over Keys / Values will throw an InvalidOperationException. Always use a copy if modification is required. like

Copy
foreach (var key in dict.Keys.ToList())
{
    dict.Remove(key);
}

2. Using for Loop with LINQ

Unlike List<T> or arrays, the Dictionary<TKey, TValue> in C# does not support direct indexing (like dict[0]). That’s because a dictionary is a hash-based collection, not an index-based. Elements are stored according to their hash codes, not their insertion order.

However, you can still access items by position using LINQ’s ElementAt() method, which allows simulated index-based iteration.

Copy
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        Dictionary<string, string> dict = new()
        {
            {"language", "C#"},
            {"topic", "Dictionary Iteration"},
            {"level", "Intermediate"}
        };
        for (int i = 0; i < dict.Count; i++)
        {
            var item = dict.ElementAt(i);
            Console.WriteLine($"Index: {i} | Key: {item.Key} | Value: {item.Value}");
        }
    }
}
Index: 0 | Key: language | Value: C#
Index: 1 | Key: topic | Value: Dictionary Iteration
Index: 2 | Key: level | Value: Intermediate
  • The ElementAt() method (from System.Linq) retrieves an element at a specific position within an enumerable sequence.
  • Internally, it enumerates items one by one until it reaches the given index.
  • This means each call to ElementAt() performs an O(n) operation.

Note : So, using ElementAt() inside a loop results in O(n²) complexity , fine for small dictionaries, but inefficient for large data sets.

For performance-sensitive tasks, prefer foreach or convert dictionary to a List first.

Copy
var items = dict.ToList();
for (int i = 0; i < items.Count; i++)
{
    Console.WriteLine($"Index: {i} | Key: {items[i].Key} | Value: {items[i].Value}");
}

This approach is O(n) overall since the conversion happens once.

3. Using ParallelEnumerable.ForAll() : Efficient Parallel Iteration for Large Data

When working with large dictionaries or computationally heavy operations, iterating sequentially using a foreach loop might become slow. C# offers a powerful solution through PLINQ (Parallel LINQ) which can distribute work across multiple CPU cores, processing elements concurrently.

By combining AsParallel() and ForAll(), you can iterate over all dictionary elements in parallel, maximizing performance for CPU-bound workloads.

Copy
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        Dictionary<string, string> dict = new()
        {
            {"language", "C#"},
            {"topic", "Dictionary"},
            {"level", "Beginner"},
            {"type", "Parallel Iteration"},
            {"performance", "High"}
        };
        dict.AsParallel().ForAll(item =>
        {
            Console.WriteLine($"Key: {item.Key} | Value: {item.Value}");
        });
    }
}
Key: topic | Value: Dictionary
Key: performance | Value: High
Key: language | Value: C#
Key: type | Value: Parallel Iteration
Key: level | Value: Beginner

How It Works (Internal Behavior)

  • AsParallel() converts the dictionary into a parallel query, enabling multiple threads to process different portions of the data simultaneously.
  • The runtime automatically partitions the source data among available CPU cores.
  • ForAll() executes the provided lambda (item => { ... }) in parallel on those partitions
  • Each thread processes its assigned elements independently, improving throughput.

This parallelism significantly speeds up CPU-intensive tasks, such as :- Data transformations, Filtering and computations, Writing logs or exporting data etc

Important Notes

Concept Description
Order Parallel processing doesn’t guarantee iteration order results may appear mixed.
Thread Safety Avoid modifying shared state (like writing to a shared variable or list) unless you use thread-safe mechanisms (e.g., locks or concurrent collections).
Best Use Case Ideal for large datasets or CPU-heavy operations where sequential iteration becomes slow.
Avoid For Small Data For small dictionaries, parallel overhead may outweigh the benefits.

4. Using String.Join() : Quick and Clean Way to Print a Dictionary

When debugging or logging data, you may want to quickly view dictionary contents without writing loops. C#’s String.Join() method makes it easy to combine all key-value pairs into a readable string, perfect for logging, debugging or quick visual inspection.

Copy
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        Dictionary<string, string> dict = new()
        {
            {"language", "C#"},
            {"topic", "Dictionary"},
            {"level", "Beginner"}
        };
        Console.WriteLine("Full Dictionary:");
        Console.WriteLine(string.Join(", ", dict.Select(kv => $"[{kv.Key}, {kv.Value}]")));
        Console.WriteLine("\nKeys:");
        Console.WriteLine(string.Join(", ", dict.Keys));
        Console.WriteLine("\nValues:");
        Console.WriteLine(string.Join(", ", dict.Values)));
    }
}
Full Dictionary:
[language, C#], [topic, Dictionary], [level, Beginner]

Keys:
language, topic, level

Values:
C#, Dictionary, Beginner