Consider this:
Requisite:
//The alphabet from a-z
List<char> letterRange = Enumerable.Range('a', 'z' - 'a' + 1)
.Select(i => (Char)i).ToList(); //97 - 122 + 1 = 26 letters/iterations
Standard foreach:
foreach (var range in letterRange)
{
Console.Write(range + ",");
}
Console.Write("\n");
Inbuilt foreach:
letterRange.ForEach(range => Console.Write(range + ",")); //delegate(char range) works as well
Console.Write("\n");
I have tried timing them against each other and the inbuilt foreach is up to 2 times faster, which seems like a lot.
I have googled around, but I can not seem to find any answers.
Also, regarding: In .NET, which loop runs faster, 'for' or 'foreach'?
for (int i = 0; i < letterRange.Count; i++)
{
Console.Write(letterRange[i] + ",");
}
Console.Write("\n");
Doesn't act execute faster than standard foreach as far as I can tell.
This is because the foreach method is not using an enumerator. Enumerators (foreach) tend to be slower then a basic for loop:
Here's the code for the ForEach method:
While I would expect there to be a difference, I'm a little surprised it's as large as you indicated. Using the enumerator approach you are taking an extra object creation, and then extra steps are taken to ensure the enumerator is not invalidated (the collection is modified). Your also going through an extra function call Current() to get the member. All this adds time.
I think your benchmark is flawed.
Console.Write
is an I/O bound task and it's the most time consuming part of your benchmark. This is a micro-benchmark and should be done very carefully for accurate results.Here is a benchmark: http://diditwith.net/PermaLink,guid,506c0888-8c5f-40e5-9d39-a09e2ebf3a55.aspx (It looks good but I haven't validated it myself). The link appears to be broken as of 8/14/2015
When you enter a foreach loop, you enumerate over each item. That enumeration causes two method calls per iteration: one to
IEnumerator<T>.MoveNext()
, and another toIEnumerator<T>.Current
. That's twocall
IL instructions.List<T>.ForEach
is faster because it has only one method call per iteration -- whatever your suppliedAction<T>
delegate is. That's onecallvirt
IL instruction. This is significantly faster than twocall
instructions.As others pointed out, IO-bound instructions like
Console.WriteLine()
will pollute your benchmark. Do something that can be confined entirely to memory, like adding elements of a sequence together.