Reputation: 1343
I'm in the process of migrating a project from Visual Basic to C# and I've had to change how a for
loop being used is declared.
In VB.NET the for
loop is declared below:
Dim stringValue As String = "42"
For i As Integer = 1 To 10 - stringValue.Length
stringValue = stringValue & " " & CStr(i)
Console.WriteLine(stringValue)
Next
Which outputs:
42 1
42 1 2
42 1 2 3
42 1 2 3 4
42 1 2 3 4 5
42 1 2 3 4 5 6
42 1 2 3 4 5 6 7
42 1 2 3 4 5 6 7 8
In C# the for
loop is declared below:
string stringValue = "42";
for (int i = 1; i <= 10 - stringValue.Length; i ++)
{
stringValue = stringValue + " " + i.ToString();
Console.WriteLine(stringValue);
}
And the output:
42 1
42 1 2
42 1 2 3
This obviously isn't correct so I had to change the code ever so slightly and included an integer variable that would hold the length of the string.
Please see the code below:
string stringValue = "42";
int stringValueLength = stringValue.Length;
for (int i = 1; i <= 10 - stringValueLength; i ++)
{
stringValue = stringValue + " " + i.ToString();
Console.WriteLine(stringValue);
}
And the output:
42 1
42 1 2
42 1 2 3
42 1 2 3 4
42 1 2 3 4 5
42 1 2 3 4 5 6
42 1 2 3 4 5 6 7
42 1 2 3 4 5 6 7 8
Now my question resolves around how Visual Basic differs to C# in terms of Visual Basic using the stringValue.Length
condition in the for
loop even though each time the loop occurs the length of the string changes. Whereas in C# if I use the stringValue.Length
in the for
loop condition it changes the initial string value each time the loop occurs. Why is this?
Upvotes: 87
Views: 6800
Reputation: 25023
In C#, the loop boundary condition is evaluated on each iteration. In VB.NET, it is only evaluated on entry to the loop.
So, in the C# version in the question, because the length of stringValue
is being changed in the loop, the final loop variable value will be changed.
In VB.NET, the final condition is inclusive, so you would use <=
instead of <
in C#.
The end condition evaluation in C# has the corollary that even if it doesn't vary but it is expensive to calculate, then it should be calculated just once before the loop.
Upvotes: 114
Reputation: 469
Because the for
in VB is a different semantic than the for
in C# (or any other C-like language)
In VB, the for
statement is specifically incrementing a counter from one value to another.
In C, C++, C#, etc., the for
statement simply evaluates three expressions:
In VB, you must supply a numeric variable which can be tested against a terminal value and incremented on each iteration
In C, C++, C#, etc., the three expressions are minimally constrained; the conditional expression must evaluate to a true/false (or integer zero/non-zero in C, C++). You don't need to perform an initialization at all, you can iterate any type over any range of values, iterate a pointer or reference over a complex structure, or not iterate anything at all.
So, in C#, etc., the condition expression must be fully evaluated on each iteration, but in VB, the terminal value of the iterator must be evaluated at the beginning, and need not be evaluated again.
Upvotes: 7
Reputation: 476
In order to make the example more understandable, I will convert both for loops into C# while loops.
VB.NET
string stringValue = "42";
int min = 1;
int max = 10 - stringValue.Length;
int i = min;
while (i <= max)
{
stringValue = stringValue + " " + stringValue.Length.ToString();
Console.WriteLine(stringValue);
i++;
}
C#
string stringValue = "42";
int i = 1;
while (i <= 10 - stringValue.Length)
{
stringValue = stringValue + " " + stringValue.Length.ToString();
Console.WriteLine(stringValue);
i++;
}
The difference is then:
VB.NET caches the maximum value for
i
, but C# recomputes it every time.
Upvotes: 11
Reputation: 32068
Now my question resolves around how VB differs to C# in terms of VB using the stringValue.Length condition in the for loop even though each time the loop occurs the length of the string changes.
According to the VB.NET documentation:
If you change the value of
counter
while inside a loop, your code might be more difficult to read and debug. Changing the value ofstart
,end
, orstep
doesn't affect the iteration values that were determined when the loop was first entered.
So, the value of To 10 - stringValue.Length
is evaluated once and reused until the loops exit.
However, look at c#'s for statement
If the
for_condition
is not present or if the evaluation yieldstrue
, control is transferred to the embedded statement. When and if control reaches the end point of the embedded statement (possibly from execution of a continue statement), the expressions of thefor_iterator
, if any, are evaluated in sequence, and then another iteration is performed, starting with evaluation of thefor_condition
in the step above.
Which basically means that the condition ; i <= 10 - stringValueLength;
is evaluated again each time.
So, as you saw, if you want to replicate the code, you need to declare the final counter in c# before starting the loop.
Upvotes: 22