I though that I know this one… I had no clue.
This simple For loop:
Dim i As Integer Dim n As Integer = 10 Dim s As Integer = 1 For i = 0 To n Step s Console.WriteLine(i) Next
compiles into this (I put it through Refelctor, so it’s easier to read). I couldn’t even get what it does with all these bit-shifts:
Dim n As Integer = 10 Dim VB$t_i4$L1 As Integer = 1 Dim VB$t_i4$L0 As Integer = n Dim i As Integer = 0 Do While (((VB$t_i4$L1 >> &H1F) Xor i) <= ((VB$t_i4$L1 >> &H1F) Xor VB$t_i4$L0)) Console.WriteLine(i) i = (i + VB$t_i4$L1) Loop
Why For loop is mutilated like this?
Probably because it’s the ‘generic way’ to cover all cases. Remember that for/step/next can go in any direction with any sign on the increment.
You used parameters on both the increment and the end-bound. The compiler has no way to know if you are going to count up or down, and if th end-bound is higher or lower than the start bound.
My guess is this is a way to get code that will work whatever you put in n and s (just a guess, I’m too tired to try and see if that is the case).
Also it makes copies of the parameters to prevent outside interference (like changing s or n during the enumeration).
=== UPDATE ===
I doubt anybody is still watching that question but I came back to this nugget just for the sake of completeness, and because I had some time. What VB is doing is a bit sneaky. The bit shift of S basically creates an integer based on the sign of S (it copies the MSB of s, ending up with &hFFFFFFFF is S is negative and &h00000000 if S is positive).
XOR of an integer value with -1 is equivalent to (-value-1). XOR with 0 is obviously a NOP. So if s is negative, it reverses both values (the -1 cancel each other) to compare them, effectively reversing the order of comparison without the need or a conditional, and thus no jump in the program flow. If s is positive it just compares them.
so, for s<0 you end up with
for s>0 you end up with
Takes me back to my 68k ASM days where such tricks where the everyday stuff (such as XOR.l D0,D0 because XORing a register with itself was faster than loading zero in it…) :p