Enumerating via interface - performance loss
c#, ienumerable, list, performance
Solution
When using `List<T>`, the `foreach` doesn't actually use the `IEnumerable<T>` interface; rather, it uses `List<T>.Enumerator`, which is a `struct`. At the trivial level, this means slightly less indirection - not having to de-reference, and using static calls rather than virtual calls - and a more direct implementation.
These differences are very very small, and in any sensible real-life example the difference is noise. However, it may be marginally noticeable if testing just the `foreach` performance.
To expand on this: `foreach` doesn't actually require `IEnumerable[<T>]` - it can work purely on the `GetEnumerator()` / `.MoveNext()` / `.Current` / `.Dispose()` pattern; this was especially important before generics in 2.0.
However, this is only possible when the variable is typed as `List<T>` (which has a custom `GetEnumerator()` method). Once you have `IEnumerable<T>`, it has to use `IEnumerator<T>`
Problem
I had a little dispute (which was very close to holy war:) ) with my colleage, about the performance of access to list via indeces VS via enumerator. To operate with some facts, I wrote the following test: ``` static void Main(string[] args) { const int count = 10000000; var stopwatch = new Stopwatch(); var list = new List<int>(count); var rnd = new Random(); for (int i = 0; i < count; i++) { list.Add( rnd.Next()); } const int repeat = 20; double indeces = 0; double forEach = 0; for (int iteration = 0; iteration < repeat; iteration++) { stopwatch.Restart(); long tmp = 0; for (int i = 0; i < count; i++) { tmp += list[i]; } indeces += stopwatch.Elapsed.TotalSeconds; stopwatch.Restart(); foreach (var integer in list) { tmp += integer; } forEach += stopwatch.Elapsed.TotalSeconds; } Console.WriteLine(indeces /repeat); Console.WriteLine(forEach /repeat); } ``` Actually, it just accesses the elements. As I expected, index access was faster. This are the results of Release build on my machine: ``` 0.0347//index access 0.0737//enumerating ``` However, I decided to change test a little: ``` //the same as before ... IEnumerable<int> listAsEnumerable = list; //the same as before ... foreach (var integer in listAsEnumerable) { tmp += integer; } ... ``` And now output was following: ``` 0.0321//index access 0.1246//enumerating (2x slower!) ``` If we are enumerating the same list via interface, the performance is 2 times slower! Why does this* happening? this means "enumerating via interface 2 times slower than enumerating the actual list". My guess is that runtime is using different `Enumerator`s: the list's in first test and a generic one in the second test.