Best Way To Iterate Through A Dictionary In C#

Best Way to Iterate Through A Dictionary Banner Image

Introduction

There are multiple ways of looping through a dictionary in C#. You can loop through just the keys, and values or both keys and values if you need both at the same time. I will dive into the different ways to loop through the method and discuss the performance implications of each. Let's look at the first example.

Dictionary Key-Value Pair Iteration

This is the more generic way to iterate through the dictionary collection. You can do this if you need access to both key and value pairs at the same time or one at the moment and then later need both. This happens by creating a foreach loop and for the type put a KeyValuePair with the types of key and value. Then the rest is the variable name with a dictionary after the in clause. This variable gives us access to both the key and the value. See the sample code below.

Dictionary<string, string> englishFrenchDictionary = new Dictionary<string, string>() { {"one","un"},{ "two","deux" }, { "three", "trois" }, { "four", "quatre" }, { "five", "cinq" } };

foreach(KeyValuePair<string,string> item in englishFrenchDictionary)//KeyValuePair keyword with the same types as the dictionary itself
{
    Console.WriteLine($"key:{item.Key}, value:{item.Value}");//Print out key and values the dictionary
}
Code Output
key:one, value:un
key:two, value:deux
key:three, value:trois
key:four, value:quatre
key:five, value:cinq

As you can see this gives access to both the key and the value. The next step is to measure how this performs.

Dictionary Key-Value Pair Iteration Speed Test

In my test, I use the following stats to measure performance..

10 tests

1000 loops per test

1 million objects


using System.Diagnostics;
int numberOfTests = 10;//Number of tests 
int numberOfFunctionCalls = 1000;//Number of function calls made per test
int numberOfObjectsToCreate = 1000000;//1 million test objects
string testName = "Dictionary Key-Value Pair Iteration";//Test name to print to average

void TestMethod(Dictionary<int,int> dictionary)
{
    int count = 0;
    foreach (KeyValuePair<int, int> item in dictionary)//KeyValuePair keyword with the same types as the dictionary itself
    {
        count++;
    }
}

List<double> testSpeedList = new List<double>();
for (int i = 0; i < numberOfTests; i++)
{
    testSpeedList.Add(StartTest());
}
Console.WriteLine($"{testName} Average speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} tests");

double StartTest()
{
    Stopwatch stopwatch = new Stopwatch();
    Dictionary<int, int> testData = GetDictionaryData();//Get intial random generated data
    for (int i = 0; i < numberOfFunctionCalls; i++)
    {
        stopwatch.Start();//Start the Stopwatch timer
        TestMethod(testData);//
        stopwatch.Stop();//Stop the Stopwatch timer
    }
    stopwatch.Stop();//Stop the Stopwatch timer
    Console.WriteLine($"Function calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
    return stopwatch.Elapsed.TotalMilliseconds;
}
Supporting Code
Dictionary<int,int> GetDictionaryData()
{
    Dictionary<int, int> testData = new Dictionary<int, int>();

    while (numberOfObjectsToCreate > testData.Count)
    {
        int item = GetRandomInt(0, 10000000);
        if(!testData.ContainsKey(item))
        {
            testData[item] = item;
        }
    }
    return testData;
}

int GetRandomInt(int minNumber, int maxNumber)
{
    Random random = new Random();//Create Random class
    int randomInt = random.Next(minNumber, maxNumber);//Get a random number between 1 and the maxnumber
    return randomInt;
}
Code Output
Function calls:1000, In 0m 5s 530ms
Function calls:1000, In 0m 5s 360ms
Function calls:1000, In 0m 5s 368ms
Function calls:1000, In 0m 5s 371ms
Function calls:1000, In 0m 5s 349ms
Function calls:1000, In 0m 5s 385ms
Function calls:1000, In 0m 5s 360ms
Function calls:1000, In 0m 5s 354ms
Function calls:1000, In 0m 5s 346ms
Function calls:1000, In 0m 5s 354ms
Dictionary Key-Value Pair Iteration Average speed:5378ms, In 10 tests

From this test, we see that looping through the Key value pairs takes about 5.3 seconds. I will test the rest of the methods as well. Let's move on to the next way.

C# Programming for Unity Game Development Specialization

COURSERA

C# Programming for Unity Game Development Specialization

4.7 (2,230 reviews)

Beginner level

No previous experience is necessary

3-months at 10 hours a week (At your pace)

$59 / month or audit, and financial aid available

If you want to learn more about C# then check out this course on Coursera. It's a 3 month course to take you through the basics of C#.

You can get started with programming using C# and apply it to Unity games in this beginner-level program. Facilitated by the University of Colorado, the program offers a chance to grasp the basics of C# and utilize the knowledge to develop Unity games.

[Full Disclosure: As an affiliate, I receive compensation if you purchase through this link]

Start Your 7-day Free Trial

Dictionary Keys Iteration

CSharp provides a way to loop through just the keys. We do this by accessing the Keys from the dictionary variable and this will loop through just the keys. The syntax looks like below.

Dictionary<string, string> englishFrenchDictionary = new Dictionary<string, string>() { { "one", "un" }, { "two", "deux" }, { "three", "trois" }, { "four", "quatre" }, { "five", "cinq" } };

foreach (string key in englishFrenchDictionary.Keys)//The type is the first parameter in the dictionary initialization 
{
    Console.WriteLine($"key:{key}");//print out keys the dictionary
}
Code Output
key:one
key:two
key:three
key:four
key:five

As expected this just prints the keys. In this case, there's an English french dictionary and only the English words are printed because they are the keys.

Dictionary Keys Iteration Speed Test

This will be the same test as before. To recap, it is 10 tests and 1 thousand function calls with 1 million objects. Let's look at the performance of this method.

using System.Diagnostics;
int numberOfTests = 10;//Number of tests 
int numberOfFunctionCalls = 1000;//Number of function calls made per test
int numberOfObjectsToCreate = 1000000;//1 million test objects
string testName = "Dictionary Key Iteration";//Test name to print to average

void TestMethod(Dictionary<int, int> dictionary)
{
    int count = 0;
    foreach (int key in dictionary.Keys)//The type is the first parameter in the dictionary initialization 
    {
        count++;
    }
}
Supporting Code
List<double> testSpeedList = new List<double>();
for (int i = 0; i < numberOfTests; i++)
{
    testSpeedList.Add(StartTest());
}
Console.WriteLine($"{testName} Average speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} tests");

double StartTest()
{
    Stopwatch stopwatch = new Stopwatch();
    Dictionary<int, int> testData = GetDictionaryData();//Get intial random generated data
    for (int i = 0; i < numberOfFunctionCalls; i++)
    {
        stopwatch.Start();//Start the Stopwatch timer
        TestMethod(testData);//
        stopwatch.Stop();//Stop the Stopwatch timer
    }
    stopwatch.Stop();//Stop the Stopwatch timer
    Console.WriteLine($"Function calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
    return stopwatch.Elapsed.TotalMilliseconds;
}

Dictionary<int, int> GetDictionaryData()
{
    Dictionary<int, int> testData = new Dictionary<int, int>();

    while (numberOfObjectsToCreate > testData.Count)
    {
        int item = GetRandomInt(0, 10000000);
        if (!testData.ContainsKey(item))
        {
            testData[item] = item;
        }
    }
    return testData;
}

int GetRandomInt(int minNumber, int maxNumber)
{
    Random random = new Random();//Create Random class
    int randomInt = random.Next(minNumber, maxNumber);//Get a random number between 1 and the maxnumber
    return randomInt;
}

Code Output
Function calls:1000, In 0m 2s 807ms
Function calls:1000, In 0m 2s 601ms
Function calls:1000, In 0m 2s 601ms
Function calls:1000, In 0m 2s 600ms
Function calls:1000, In 0m 2s 605ms
Function calls:1000, In 0m 2s 605ms
Function calls:1000, In 0m 2s 595ms
Function calls:1000, In 0m 2s 600ms
Function calls:1000, In 0m 2s 599ms
Function calls:1000, In 0m 2s 604ms
Dictionary Keys Iteration Average speed:2622ms, In 10 tests

For the dictionary key iteration test, we see that it takes about 2.6 seconds. It is faster than loop through both the key and value at the same time.

Dictionary Keys Then Dictionary Access Iteration

This method uses a combination of looping through the keys and then using the key to access the value from the dictionary itself while in the foreach loop. This will use the speed of the Dictionary Keys method and the fast access of the dictionary to our advantage. See the syntax below.

Dictionary<string, string> englishFrenchDictionary = new Dictionary<string, string>() { { "one", "un" }, { "two", "deux" }, { "three", "trois" }, { "four", "quatre" }, { "five", "cinq" } };

foreach (string key in englishFrenchDictionary.Keys)//The type is the first parameter in the dictionary initialization 
{
    Console.WriteLine($"key:{key}, value:{englishFrenchDictionary[key]}");//print out keys and values the dictionary
}
Code Output
key:one, value:un
key:two, value:deux
key:three, value:trois
key:four, value:quatre
key:five, value:cinq

Dictionary Keys Then Dictionary Access Iteration Speed Test

Next I'll perform a speed test for this method. It will have the same parameters as the other tests. Below are the test code and output.

using System.Diagnostics;
int numberOfTests = 10;//Number of tests 
int numberOfFunctionCalls = 1000;//Number of function calls made per test
int numberOfObjectsToCreate = 1000000;//1 million test objects
string testName = "Dictionary Keys Then Dictionary Access Iteration";//Test name to print to average

void TestMethod(Dictionary<int, int> dictionary)
{
    int count = 0;
    foreach (int key in dictionary.Keys)//The type is the first parameter in the dictionary initialization 
    {
        int value = dictionary[key];
        count++;
    }
}
Supporting Code
List<double> testSpeedList = new List<double>();
for (int i = 0; i < numberOfTests; i++)
{
    testSpeedList.Add(StartTest());
}
Console.WriteLine($"{testName} Average speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} tests");

double StartTest()
{
    Stopwatch stopwatch = new Stopwatch();
    Dictionary<int, int> testData = GetDictionaryData();//Get intial random generated data
    for (int i = 0; i < numberOfFunctionCalls; i++)
    {
        stopwatch.Start();//Start the Stopwatch timer
        TestMethod(testData);//
        stopwatch.Stop();//Stop the Stopwatch timer
    }
    stopwatch.Stop();//Stop the Stopwatch timer
    Console.WriteLine($"Function calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
    return stopwatch.Elapsed.TotalMilliseconds;
}

Dictionary<int, int> GetDictionaryData()
{
    Dictionary<int, int> testData = new Dictionary<int, int>();

    while (numberOfObjectsToCreate > testData.Count)
    {
        int item = GetRandomInt(0, 10000000);
        if (!testData.ContainsKey(item))
        {
            testData[item] = item;
        }
    }
    return testData;
}

int GetRandomInt(int minNumber, int maxNumber)
{
    Random random = new Random();//Create Random class
    int randomInt = random.Next(minNumber, maxNumber);//Get a random number between 1 and the maxnumber
    return randomInt;
}
Code Output
Function calls:1000, In 0m 25s 139ms
Function calls:1000, In 0m 26s 281ms
Function calls:1000, In 0m 24s 464ms
Function calls:1000, In 0m 26s 258ms
Function calls:1000, In 0m 25s 629ms
Function calls:1000, In 0m 26s 41ms
Function calls:1000, In 0m 24s 334ms
Function calls:1000, In 0m 28s 907ms
Function calls:1000, In 0m 25s 370ms
Function calls:1000, In 0m 27s 63ms
Dictionary Keys Then Dictionary Access Iteration Average speed:25949ms, In 10 tests

This is the slowest method, the test took about 25 seconds. This is slow that it shouldn't be used in high volume cases.

Dictionary Values Iteration

Another way to iterate through the dictionary is to loop through its values. We can do this by the property Values from the dictionary variable. The type of the dictionary value is assigned in the second parameter in the initialization of the dictionary. Check out the syntax below.

Dictionary<string, string> englishFrenchDictionary = new Dictionary<string, string>() { { "one", "un" }, { "two", "deux" }, { "three", "trois" }, { "four", "quatre" }, { "five", "cinq" } };

foreach (string value in englishFrenchDictionary.Values)//The type is the second parameter in the dictionary initialization 
{
    Console.WriteLine($"value:{value}");//print out keys the dictionary
}
Code Output
value:un
value:deux
value:trois
value:quatre
value:cinq

Dictionary Values Iteration Speed Test

I will test this method just as before. Let's see how Values performs compared to the others.


using System.Diagnostics;
int numberOfTests = 10;//Number of tests 
int numberOfFunctionCalls = 1000;//Number of function calls made per test
int numberOfObjectsToCreate = 1000000;//1 million test objects
string testName = "Dictionary Values Iteration";//Test name to print to average

void TestMethod(Dictionary<int, int> dictionary)
{
    int count = 0;
    foreach (int value in dictionary.Values)//The type is the second parameter in the dictionary initialization 
    {
        count++;
    }
}

Supporting Code

List<double> testSpeedList = new List<double>();
for (int i = 0; i < numberOfTests; i++)
{
    testSpeedList.Add(StartTest());
}
Console.WriteLine($"{testName} Average speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} tests");

double StartTest()
{
    Stopwatch stopwatch = new Stopwatch();
    Dictionary<int, int> testData = GetDictionaryData();//Get intial random generated data
    for (int i = 0; i < numberOfFunctionCalls; i++)
    {
        stopwatch.Start();//Start the Stopwatch timer
        TestMethod(testData);//
        stopwatch.Stop();//Stop the Stopwatch timer
    }
    stopwatch.Stop();//Stop the Stopwatch timer
    Console.WriteLine($"Function calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
    return stopwatch.Elapsed.TotalMilliseconds;
}

Dictionary<int, int> GetDictionaryData()
{
    Dictionary<int, int> testData = new Dictionary<int, int>();

    while (numberOfObjectsToCreate > testData.Count)
    {
        int item = GetRandomInt(0, 10000000);
        if (!testData.ContainsKey(item))
        {
            testData[item] = item;
        }
    }
    return testData;
}

int GetRandomInt(int minNumber, int maxNumber)
{
    Random random = new Random();//Create Random class
    int randomInt = random.Next(minNumber, maxNumber);//Get a random number between 1 and the maxnumber
    return randomInt;
}
Code Output
Function calls:1000, In 0m 2s 800ms
Function calls:1000, In 0m 2s 610ms
Function calls:1000, In 0m 2s 616ms
Function calls:1000, In 0m 2s 597ms
Function calls:1000, In 0m 2s 606ms
Function calls:1000, In 0m 2s 603ms
Function calls:1000, In 0m 2s 616ms
Function calls:1000, In 0m 2s 600ms
Function calls:1000, In 0m 2s 598ms
Function calls:1000, In 0m 2s 598ms
Dictionary Values Iteration Average speed:2625ms, In 10 tests

This performs just as well as looping through the Keys as expected it is about 2.6 seconds.

Deconstructor of Dictionary Iteration

There's a way in C# 7.0 to deconstructor the key and value into two separate variables This improves the readability of the syntax of the KeyValuePair type and makes explicit the key and value variables in the foreach loop. See the syntax below.

Dictionary<string, string> englishFrenchDictionary = new Dictionary<string, string>() { { "one", "un" }, { "two", "deux" }, { "three", "trois" }, { "four", "quatre" }, { "five", "cinq" } };

foreach (var (key, value) in englishFrenchDictionary)//Deconstruct dictionary into key and value variables
{
    Console.WriteLine($"key:{key}, value:{value}");//print out key and values the dictionary
}

Code Output
key:one, value:un
key:two, value:deux
key:three, value:trois
key:four, value:quatre
key:five, value:cinq

Dictionary with Deconstructor Iteration Speed Test


using System.Diagnostics;
int numberOfTests = 10;//Number of tests 
int numberOfFunctionCalls = 1000;//Number of function calls made per test
int numberOfObjectsToCreate = 1000000;//1 million test objects
string testName = "Dictionary with Deconstructor";//Test name to print to average

void TestMethod(Dictionary<int, int> dictionary)
{
    int count = 0;
    foreach (var (key, value) in dictionary)//The type is the second parameter in the dictionary initialization 
    {
        count++;
    }
}


Supporting Code
List<double> testSpeedList = new List<double>();
for (int i = 0; i < numberOfTests; i++)
{
    testSpeedList.Add(StartTest());
}
Console.WriteLine($"{testName} Average speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} tests");

double StartTest()
{
    Stopwatch stopwatch = new Stopwatch();
    Dictionary<int, int> testData = GetDictionaryData();//Get intial random generated data
    for (int i = 0; i < numberOfFunctionCalls; i++)
    {
        stopwatch.Start();//Start the Stopwatch timer
        TestMethod(testData);//
        stopwatch.Stop();//Stop the Stopwatch timer
    }
    stopwatch.Stop();//Stop the Stopwatch timer
    Console.WriteLine($"Function calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
    return stopwatch.Elapsed.TotalMilliseconds;
}

Dictionary<int, int> GetDictionaryData()
{
    Dictionary<int, int> testData = new Dictionary<int, int>();

    while (numberOfObjectsToCreate > testData.Count)
    {
        int item = GetRandomInt(0, 10000000);
        if (!testData.ContainsKey(item))
        {
            testData[item] = item;
        }
    }
    return testData;
}

int GetRandomInt(int minNumber, int maxNumber)
{
    Random random = new Random();//Create Random class
    int randomInt = random.Next(minNumber, maxNumber);//Get a random number between 1 and the maxnumber
    return randomInt;
}
Code Output
Function calls:1000, In 0m 7s 212ms
Function calls:1000, In 0m 7s 8ms
Function calls:1000, In 0m 6s 992ms
Function calls:1000, In 0m 7s 18ms
Function calls:1000, In 0m 7s 0ms
Function calls:1000, In 0m 6s 975ms
Function calls:1000, In 0m 7s 5ms
Function calls:1000, In 0m 6s 982ms
Function calls:1000, In 0m 7s 22ms
Function calls:1000, In 0m 7s 40ms
Dictionary with Deconstructor Average speed:7026ms, In 10 tests

This result at around 7 seconds is slightly making this the slowest of the methods to iterate through.

List With Key Value Class Iteration

This is a custom class I created to hold a dictionary and a list. As the key-value pairs are added to the dictionary, they are also added to a list. This list will be looped through later instead of the dictionary for added performance to the iteration process. Let's look at the code.

DictionaryContainer<string,string> englishFrenchDictionary = new DictionaryContainer<string, string>();
englishFrenchDictionary.AddKeyValueToDictionary("one", "un");//Add key and Value to the dictionary and list
englishFrenchDictionary.AddKeyValueToDictionary("two", "deux");//Add key and Value to the dictionary and list
englishFrenchDictionary.AddKeyValueToDictionary("three", "trois");//Add key and Value to the dictionary and list
englishFrenchDictionary.AddKeyValueToDictionary("four", "quatre");//Add key and Value to the dictionary and list
englishFrenchDictionary.AddKeyValueToDictionary("five", "cinq");//Add key and Value to the dictionary and list

foreach (CustomKeyValuePair<string,string> customKeyValuePair in englishFrenchDictionary.List)//Deconstruct dictionary into key and value variables
{
    Console.WriteLine($"key:{customKeyValuePair.Key}, value:{customKeyValuePair.Value}");//print out key and values the dictionary
}

class DictionaryContainer<TKey, TValue>
{
    public Dictionary<TKey, TValue> Dictionary { get; set; } = new Dictionary<TKey, TValue>();
    public List<CustomKeyValuePair<TKey,TValue>> List { get; set; } = new List<CustomKeyValuePair<TKey, TValue>>();

    public void AddKeyValueToDictionary(TKey key, TValue value)
    {
        if (!Dictionary.ContainsKey(key))//If the key is not in the dictionary then it's safe to add it
        {
            Dictionary[key] = value;//Add key and value to the dictionary
            CustomKeyValuePair<TKey, TValue> customKeyValuePair = new CustomKeyValuePair<TKey, TValue>(key, value);
            List.Add(customKeyValuePair);//Add key-value pair class to the list.
        }
    }
}

class CustomKeyValuePair<TKey, TValue>
{
    public CustomKeyValuePair(TKey key, TValue value)
    {
        Key = key;
        Value = value;
    }

    public TKey Key { get; set; }
    public TValue Value { get; set; }
}

Code Output
key:one, value:un
key:two, value:deux
key:three, value:trois
key:four, value:quatre
key:five, value:cinq

This gives us the correct output by saving the items in a list instead and printing out the pairs from a class. Next, we'll test the performance.

List With Key Value Class Speed Test Iteration

Next, I'm going to test the speed of this method from the speed test to see how it compares with the other dictionary-based methods.


using System.Diagnostics;
int numberOfTests = 10;//Number of tests 
int numberOfFunctionCalls = 1000;//Number of function calls made per test
int numberOfObjectsToCreate = 1000000;//1 million test objects
string testName = "List With Key Value Class";//Test name to print to average

void TestMethod(DictionaryContainer<int, int> dictionaryContainer)
{
    int count = 0;
    foreach (CustomKeyValuePair<int,int> customKeyValuePair in dictionaryContainer.List)//The type is the second parameter in the dictionary initialization 
    {
        count++;
    }
}

List<double> testSpeedList = new List<double>();
for (int i = 0; i < numberOfTests; i++)
{
    testSpeedList.Add(StartTest());
}
Console.WriteLine($"{testName} Average speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} tests");

Supporting Code

double StartTest()
{
    Stopwatch stopwatch = new Stopwatch();
    DictionaryContainer<int,int> testData = GetDictionaryData();//Get intial random generated data
    for (int i = 0; i < numberOfFunctionCalls; i++)
    {
        stopwatch.Start();//Start the Stopwatch timer
        TestMethod(testData);//
        stopwatch.Stop();//Stop the Stopwatch timer
    }
    stopwatch.Stop();//Stop the Stopwatch timer
    Console.WriteLine($"Function calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
    return stopwatch.Elapsed.TotalMilliseconds;
}

DictionaryContainer<int,int> GetDictionaryData()
{
    DictionaryContainer<int, int> dictionaryContainer = new DictionaryContainer<int, int>();
    while (numberOfObjectsToCreate > dictionaryContainer.Dictionary.Count)
    {
        int item = GetRandomInt(0, 10000000);
        dictionaryContainer.AddKeyValueToDictionary(item, item);
    }
    return dictionaryContainer;
}

int GetRandomInt(int minNumber, int maxNumber)
{
    Random random = new Random();//Create Random class
    int randomInt = random.Next(minNumber, maxNumber);//Get a random number between 1 and the maxnumber
    return randomInt;
}

class DictionaryContainer<TKey, TValue>
{
    public Dictionary<TKey, TValue> Dictionary { get; set; } = new Dictionary<TKey, TValue>();
    public List<CustomKeyValuePair<TKey, TValue>> List { get; set; } = new List<CustomKeyValuePair<TKey, TValue>>();

    public void AddKeyValueToDictionary(TKey key, TValue value)
    {
        if (!Dictionary.ContainsKey(key))//If key is not in the dictionary then it's safe to add it
        {
            Dictionary[key] = value;//Add key and value to the dictionary
            CustomKeyValuePair<TKey, TValue> customKeyValuePair = new CustomKeyValuePair<TKey, TValue>(key, value);
            List.Add(customKeyValuePair);//Add key-value pair class to the list.
        }
    }
}

class CustomKeyValuePair<TKey, TValue>
{
    public CustomKeyValuePair(TKey key, TValue value)
    {
        Key = key;
        Value = value;
    }

    public TKey Key { get; set; }
    public TValue Value { get; set; }
}
Code Output
Function calls:1000, In 0m 3s 572ms
Function calls:1000, In 0m 3s 436ms
Function calls:1000, In 0m 3s 432ms
Function calls:1000, In 0m 3s 433ms
Function calls:1000, In 0m 3s 427ms
Function calls:1000, In 0m 3s 442ms
Function calls:1000, In 0m 3s 437ms
Function calls:1000, In 0m 3s 434ms
Function calls:1000, In 0m 3s 431ms
Function calls:1000, In 0m 3s 421ms
List With Key Value Class Average speed:3447ms, In 10 tests

Using a list to cluster the key and value pairs in the class is pretty fast and approaching the speed of the Keys and Values of the dictionary speed.

Conclusion

Overall RankMethodSpeed
1Dictionary Keys2622ms
1Dictionary Values2625ms
2List With Key Value Class3447ms
3Dictionary Key-Value Pair5378ms
4Deconstructor of Dictionary7026ms
5Dictionary Keys Then Dictionary Access25949ms

The way to iterate through a dictionary is to use the Dictionary Keys and Dictionary Values methods. They have the best performance but they only give Keys or Values. If you want to have access to both Keys and Values at the same time then it would be best to use a list to package them together in a class. But if you're restricted to only a dictionary then Dictionary's Key-Value Pair method is good enough too. Next is the deconstructor of the dictionary, I think this can be avoided because it is slower than the Key-Value Pair method that is natively supported in the dictionary. The readability gains from this are not worth the loss in performance. The last method on the list is extremely slow and should be avoided and that is the Dictionary Keys Then Dictionary Access method. It suffers as the dictionary grows in size. This does not scale.

Do you have any other methods of iterating through a dictionary? Let me know in the comments.

Get Latest Updates