vb.net

How does For loop work in VB.NET?


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?


Solution

  • 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

    while (-i-1)<=(-n-1) 
    ==> while -i <= -n
    ==> while i>=n
    

    for s>0 you end up with

    while i <= n
    

    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