Although this is completely micro-optimization, it will never be a performance bottleneck. Interestingly, the two are actually different, I wonder when you retrieve the methods as in loops with VS2010, I get the following:
private static String forLoop(ref Int64 i) { String x; for (; FIVE_BN > i; i++) x = null; //Replace with only ; in both loops and the for loop is faster return x; } private static void whileloop(ref String x, ref Int64 i) { while (FIVE_BN > i++) x = null; //Replace with only ; in both loops and the for loop is faster }
And this is quite interesting ... it shows that the two functions are really different.
now that we are replacing logic in a loop ; , instead, we get the following extracted methods:
private static Int64 forLoopShort(Int64 i) { for (; FIVE_BN > i; i++) ; //Replace with only ; in both loops and the for loop is faster return i; } private static Int64 whileLoopShort(Int64 i) { while (FIVE_BN > i++) ; //Replace with only ; in both loops and the for loop is faster return i; }
Which indicates why loops mostly work with this configuration.
To understand how they differ when embedding (and are not retrieved into methods), we need to look at how the optimized CLR code looks (although the optimizer can actually remove any significant differences between the two functions). This is something for later editing.
Edit:
CIL shows the differences:
The For loop has .maxstack 2 , but the while loop has .maxstack 4 , otherwise there is a slight difference in the order of operations because the increment for while occurs at the beginning of the loop, but for operation is performed at the end of the loop (change the contents of the loop on Console.WriteLine(i) and see that the While loop will print from 1, but the For loop will print from 0 (both do the same number of loop iterations, though).
When the contents of the loop are only equal ; , both loops in CIL are reduced by 2 lines, and the following lines are deleted (for both loops):
IL_0006: ldnull IL_0007: stloc.0
However, when we create in the release, the code is very different:
The difference between x = null; and ; is nothing for any of the loops, as the optimizer has noticed that the value never changes to nonempty.
The difference between the optimized while and while loops is as follows:
CIL for loop:
IL_0000: ldc.i4.0 IL_0001: conv.i8 IL_0002: stloc.0 IL_0003: br.s IL_000a IL_0005: ldloc.0 IL_0006: ldc.i4.1 IL_0007: conv.i8 IL_0008: add IL_0009: stloc.0 IL_000a: ldc.i8 0x12a05f200 IL_0013: ldloc.0 IL_0014: bgt.s IL_0005 IL_0016: ret
And the CIL while :
IL_0000: ldc.i4.0 IL_0001: conv.i8 IL_0002: stloc.0 IL_0003: ldc.i8 0x12a05f200 IL_000c: ldloc.0 IL_000d: dup IL_000e: ldc.i4.1 IL_000f: conv.i8 IL_0010: add IL_0011: stloc.0 IL_0012: bgt.s IL_0003 IL_0014: ret
So, we see that the optimized while loop is faster than the for loop by 2 operations, however it uses more stack space.
The difference between the two seems completely related to the difference in where i++ happens.
In fact, this is confirmed by the creation of a new method:
private static void forLoopVeryShort() { string x; Int64 i = 0; for (; FIVE_BN > i++;) ;
The CIL code for this for method when building (in release or debugging) is identical to the while code.
There is your difference. For loops, it executes in exactly the same way as for loops when they perform the same behavior. The difference you noticed is entirely related to running the code in debugging, not release, in combination with JIT, which is not always effective as an optimizer for release code.
I liked this question, I learned something from it; I hope others do. +1