Introduction
Iterating through collections is part and parcel of programming. As a C# developer you’ve probably used for
and foreach
. Both helps to iterate through a collection, but it’s worth to be aware that there are ins and outs. In this post I will show and explain performance differences between iterating through an array and a list using for
and foreach
.
Performance
Let’s consider the following code snippet:
public class CollectionsHolder
{
private readonly List<int> _list;
private readonly int[] _array;
public CollectionsHolder(int count)
{
_list = new List<int>(Enumerable.Range(0, count));
_array = new int[count];
}
public void ForLoopList()
{
for (int i = 0; i < _list.Count; i++) { }
}
public void ForeachLoopList()
{
foreach (var item in _list) { }
}
public void ForLoopArray()
{
for (int i = 0; i < _array.Length; i++) { }
}
public void ForeachLoopArray()
{
foreach (var item in _array) { }
}
}
The CollectionsHolder
class stores two collections: _list
and _array
. There are four methods that do nothing but iterate through a particular collection – pretty useless but good enough in terms of benchmarking.
Benchmark (1_000_000_000 elements per collection) results for these four methods stand as follows:
It turns out that foreach
iteration time is ~7 times slower than using classic for
when it comes to the list iteration. Surprisingly, foreach
iteration through the array lasts the same as using for
loop. The question is, why ForLoopList
, ForLoopArray
and ForeachLoopArray
last the same, meanwhile ForeachLoopList
lasts much longer?
Explanation
To get immediate insight I strongly recommend to visit the sharplab.io website. Long story short, the sharplab.io can be used e.g. to see the C# (without syntactic sugar), IL or ASM translation of the C# code (F#, Visual Basic and IL as well at the time of writing the post).
Once you’re there just paste the aforementioned code snippet and focus on the right side:
As you can see the code from the left side has been translated into the code on the right side (no syntactic sugar). The mystery seems to be solved! The ForLoopList
, ForLoopArray
and ForeachLoopArray
methods have been translated into straightforward while
loop, hence the execution time of the methods are almost the same (~330ms in our benchmark). However, the ForeachLoopList
looks slightly more complicated. These additional lines of code, i.e. getting enumerator ( _list.GetEnumerator()
), using enumerator.MoveNext()
and so on, cause additional overhead in terms of the method execution time.
Summary
In conclusion, for
and foreach
, despite the similar usage, might perform differently in terms of time execution. Having that in mind you might think, that you should use for
any time, but don’t be fooled. There is something called “premature optimization” – it is a tendency to spend to much time to optimize unnecessary things. Don’t get me wrong, optimization is crucial, but you should always take into consideration if it is reasonable. Moreover, using foreach
has its pros, e.g. using it against a list is (in my opinion) much more readable. Readability is sometimes undervalued. Poorly written code is hard to understand, therefore its maintenance is more expensive.
As always I’ve prepared an example and you can find it on my github, project: for-vs-foreach, benchmark project: for-vs-foreach-benchmark. I encourage you to go through the code, debug it and try to test your own scenarios.
Have a nice day, bye!
Be First to Comment