[This post is part of a series, "wish-list for future versions of VB"]

 

IDEA: In a "For Each" loop, put the loop control variable's scope inside the loop. Look at the following code:

        Dim lambdas(10) As Func(Of Integer, Integer)

        For x = 1 To 10

            lambdas(x) = Function(i) i + x

        Next

 

        Dim add5 = lambdas(5)(1) ' evaluates to 12: should evaluate to 6

You'd expect it to assign "6" to the variable, because the 5th lambda should have been one that adds the number 5 to its argument. But in both VB and C#, the scope of "x" is actually the entire loop, and so every lambda shares the same "x", and it by the end of the loop it ends up with the value 11, and hence the answer 12.

VB currently warns you about this: "warning BC42324: Using the iteration variable in a lambda expression may have unexpected results." Too right it has unexpected results! Unfortunately, the compiler has no way in general of knowing whether your use of the iteration variable is safe or not, so you also get the warning in safe code:

        For x = 1 To 10

            Dim y = From i In {1, 2, 3, 4, 5} Where i < x Select i

            Console.WriteLine(y.Count)

        Next

 

VB should put the scope of the variable inside the loop. This will make the code work in the obvious way. It would be a breaking change, of course (e.g. the first sample would print "6" rather than "12"). But every case that it breaks is a case where the VB compiler already gives a warning.

Note that this issue becomes more important as we add more features to the language which use "delayed execution" blocks -- things like lamdas, LINQ, async and anonymous iterators will all run into the same issue.

 

Provisional evaluation from VB team: This is a decent idea, one that will rise in importance as we add further delayed-execution constructs to the language.