In this article, we will compare the for and foreach loops. Iterating through arrays and lists is fundamental when learning any programming language. C# offers different ways to achieve this, such as using while, for, and foreach statements.

But, what about the differences between different loops? Comparing for and foreach loops in C# and understanding their differences aids us in writing efficient code.

To download the source code for this article, you can visit our GitHub repository.

Without further delay, let’s start!

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

For Loop Statement in C#

As we all know, the for loop is a general-purpose loop that we typically use to iterate through an indexable object while executing some statements and has this syntax:

for (initialization; condition; increment)
{
    // statements
}

If our set conditions remain true, we can initialize our counter and iterate through a collection. 

How foreach Works in C#?

Besides the for loop, we can use the foreach loop to iterate through an IEnumerable object:

foreach (element in iterable-item)
{
    // statements
}

Here, we can see that the foreach statement does not need initialization and a counter, unlike the for loop, making it easier to iterate through an object. 

Comparing the Low-Level Implementation of for and foreach loops in C#

Assuming we have an array of elements that we want to output to the console using a for loop:

public void PrintArray(int[] array) 
{    
    for (int i = 0; i < array.Length; i++)
    {
        Console.WriteLine(array[i]);
    }
}

Using SharpLab, let’s see the lowered version of the same snippet: 

[NullableContext(1)]
public void PrintArray(int[] array)
{
    int num = 0;
    while (num < array.Length)
    {
        Console.WriteLine(array[num]);
        num++;
    }
}

Next, we are going to repeat the same process using a foreach loop:

public void PrintArray(int[] array) 
{    
    foreach (var element in array)
    {
        Console.WriteLine(element);
    }
}

Finally, let’s see the lowered version of the same function:

[NullableContext(1)]
public void PrintArray(int[] array)
{
    int num = 0;
    while (num < array.Length)
    {
        int value = array[num];
        Console.WriteLine(value);
        num++;
    }
}

We can see that the for loop and foreach loop are identical behind the scenes. However, the compiler output may differ based on logic or underlying data structures.

For example, let’s assume we are iterating through a List<int> object and finding the sum of its elements:

public static long SumWithFor(List<int> data)
{
    var sum = 0L;
    for(int i=0; i < data.Capacity; ++i)
    {
        sum += data[i];
    }
    
    return sum;
}

public static long SumWithForEach(List<int> data)
{
    var sum = 0L;
    foreach(var val in data)
    {
        sum += val;
    }
    
    return sum;
}

Finally, let’s review it’s lowered version:

public static long SumWithFor(List<int> data)
{
    long num = 0L;
    int num2 = 0;
    while (num2 < data.Capacity)
    {
        num += data[num2];
        num2++;
    }
    return num;
}

public static long SumWithForEach(List<int> data)
{
    long num = 0L;
    List<int>.Enumerator enumerator = data.GetEnumerator();
    try
    {
        while (enumerator.MoveNext())
        {
            int current = enumerator.Current;
            num += current;
        }
        return num;
    }
    finally
    {
        ((IDisposable)enumerator).Dispose();
    }
}

We can see that although the for and foreach loops utilize the while loop, the latter in this case, uses the Enumerator() object to iterate over the elements of the collection and is disposed of after the iteration process is complete.

Note, in .NET 7 and 8, while the lowering of a foreach on a List<T> still generates code that initializes an enumerator; there were changes to the JIT compiler to optimize the performance of List<T> enumeration.

Compare For and Foreach Loops Performance in C#

Let’s test how the for and foreach loops compare when iterating through common data structures in C#. For these tests, we check how long it takes to find the sum of 10,000,000 integers:

| Method                 | Mean      | Error     | StdDev    | Rank | Allocated |
|----------------------- |----------:|----------:|----------:|-----:|----------:|
| ArrayUsingForeach      |  3.552 ms | 0.0130 ms | 0.0108 ms |    1 |       2 B |
| ArrayUsingForLoop      |  4.845 ms | 0.0148 ms | 0.0115 ms |    2 |       3 B |
|                        |           |           |           |      |           |
| DictionaryUsingForeach | 13.702 ms | 0.1392 ms | 0.1234 ms |    1 |       6 B |
| DictionaryUsingForLoop | 37.431 ms | 0.2907 ms | 0.2577 ms |    2 |      33 B |
|                        |           |           |           |      |           |
| ListUsingForLoop       |  5.429 ms | 0.0403 ms | 0.0357 ms |    1 |       3 B |
| ListUsingForeach       |  5.433 ms | 0.0259 ms | 0.0216 ms |    1 |       3 B |

Generally, the foreach loop outshines its for loop counterpart when iterating over arrays. When iterating over lists the performance is nearly identical. However, we benefit from having more control over the iteration logic when using for loop. 

This benchmark was performed using the latest .NET version. Performance of foreach will vary greatly on older .NET versions due to more recent optimizations.

Besides that, iterating through dictionaries using for loop requires us to define our logic to work with the <TKey, TValue> pairs, which makes using this technique slower than the foreach loop, where we have direct access to the elements.

Pros and Cons of Using for and Foreach Loop in C#

First, the awaitable foreach loop allows iterating through asynchronous data streams for collections implementing the IAsyncEnumerable<T> interface. With each iteration, we can suspend the process as we wait for the retrieval of the next element asynchronously, unlike using the for loop. 

Besides that, in situations where we need to perform some actions on every element of a type that implements the IEnumerable<T> interface, the foreach loop is the best bet. On the other hand, in cases where we need to access elements using their indices, do an action a fixed number of times, or need complex control over the flow, the for loop is the best solution. 

In terms of code readability, foreach is cleaner, abstracting from collections and the iteration process. It also works if the collection type changes, unlike a for loop, requiring us to refactor the code. For example, if we change an array into a list, we need to change the Length property to Count while initializing the loop. 

Finally, the for loop can come in handy in situations where we need to make changes to a collection, such as adding and removing elements, which is not possible when using the foreach loop. 

Conclusion 

In this article, we learned how the for and foreach statements work in C#. We also learned the strengths and weaknesses of each statement when iterating through different data structures. Which one do you prefer? Let us know in the comments section below. 

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!