1

Iterating over an array or a list that has no element, foreach seems very slow compared to for. Running below code, the result I got is:

3ms
143ms
7ms

Is foreach really slow or am I doing something wrong?

var l = new List<int>();
var watch = new Stopwatch();
var test = 0;

watch.Start();
for (int i = 0; i < 10000000; i++) 
    if (l.Count > 0) 
        test = 1;
watch.Stop();
Debug.Log(watch.ElapsedMilliseconds);

watch.Reset();
watch.Start();
for (int i = 0; i < 10000000; i++) 
    foreach (var item in l) 
        test = 1;
watch.Stop();
Debug.Log(watch.ElapsedMilliseconds);

watch.Reset();
watch.Start();
for (int i = 0; i < 10000000; i++) 
    for (int j = 0; j < l.Count; j++) 
        test = 1;
watch.Stop();
Debug.Log(watch.ElapsedMilliseconds);
maccettura
  • 10,514
  • 3
  • 28
  • 35
Elonoa
  • 467
  • 7
  • 19
  • 8
    Leaving aside any questions about the validity of your timing - You are doing something **ten million times** and it is taking **one seventh** of a second. Is this *really* a problem? Can you reasonably call this "really slow"? – AakashM Feb 01 '19 at 23:32
  • In my other project I was using foreach a lot when often the list being foreach-ed doesn't have any element. So I was just wondering if I should replace it with "for" or check if the list has no element before foreach-ing, for performance wise. – Elonoa Feb 01 '19 at 23:38
  • The `foreach` loop requires the use of an [`Enumerator`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.ienumerator?view=netframework-4.7.2), which has a `Current` property and `MoveNext` method that get called each time, so it will be slower. – Rufus L Feb 01 '19 at 23:51
  • 1
    This is very situation specific. `foreach` works on any `IEnumerable`. Just seeing if an `IEnumerable` has any elements will require getting the enumerator for the object. If you're always working with collections that have a Count you can reference then maybe the check makes sense, but ....no, not even then. Don't clutter your code with stuff like that. It just makes it less readable. "Why are they checking if there are any elements before iterating?!" Like @AakashM said, the time taken over 10 million iterations is still just the blink of an eye. Just keep your code clean and foreach. – itsme86 Feb 01 '19 at 23:51
  • Thank you for the explanations. Now I understood why it was slow. I don't intened to put checks on every foreach code I use but the very part of my project needed some optimization. – Elonoa Feb 02 '19 at 00:00
  • 1
    To sum up, yes, `for` is almost always *slightly* faster than `foreach`, at least for types that support constant time by-index access. However, both are extremely fast and unless you're building an application that relies heavily on matrix mathematics or other highly specialized use case, you really shouldn't worry about it. Optimize for readability first and then, if you have evidence that it's necessary, for performance. – p.s.w.g Feb 02 '19 at 00:33
  • @Elonoa Can you tell me why you are iterating over empty list? – Ondřej Kubíček Feb 02 '19 at 15:48

1 Answers1

5

A foreach loop requires the use of an Enumerator to iterate over the collection, which requires accessing the Current property and calling the MoveNext method on each iteration, which take some processing time.

The for loop only has to call get_Item on each iteration, so that’s one less call than the foreach loop, which makes a slight difference in performance.

Rufus L
  • 36,127
  • 5
  • 30
  • 43