为什么将 VB.NET 代码迁移到 C# 时 for 循环的行为会有所不同?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52607611/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 20:25:58  来源:igfitidea点击:

Why does a for loop behave differently when migrating VB.NET code to C#?

c#vb.netloopsfor-loop

提问by slee423

I'm in the process of migrating a project from Visual Basic to C# and I've had to change how a forloop being used is declared.

我正在将一个项目从 Visual Basic 迁移到 C#,我不得不更改for正在使用的循环的声明方式。

In VB.NET the forloop is declared below:

在 VB.NET 中,for循环声明如下:

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 forloop is declared below:

在 C# 中,for循环声明如下:

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.Lengthcondition in the forloop even though each time the loop occurs the length of the string changes. Whereas in C# if I use the stringValue.Lengthin the forloop condition it changes the initial string value each time the loop occurs. Why is this?

现在我的问题解决了 Visual Basic 与 C# 在 Visual Basic 方面使用循环中的stringValue.Length条件有何不同,for即使每次发生循环时字符串的长度都会发生变化。而在C#如果我使用stringValue.Lengthfor循环条件它的每个环路发生时改变初始字符串值。为什么是这样?

回答by Andrew Morton

In C#, the loop boundary condition is evaluated on each iteration. In VB.NET, it is only evaluated on entry to the loop.

在 C# 中,每次迭代都会评估循环边界条件。在 VB.NET 中,它仅在进入循环时进行评估。

So, in the C# version in the question, because the length of stringValueis being changed in the loop, the final loop variable value will be changed.

因此,在问题中的 C# 版本中,由于stringValue循环中的长度正在更改,因此最终循环变量值将更改。

In VB.NET, the final condition is inclusive, so you would use <=instead of <in C#.

在 VB.NET 中,最终条件是包含的,因此您将在 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.

C# 中的结束条件评估有一个推论,即使它没有变化但计算成本很高,那么它也应该在循环之前计算一次。

回答by Camilo Terevinto

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.

现在我的问题解决了 VB 与 C# 在 VB 方面使用 for 循环中的 stringValue.Length 条件有何不同,即使每次循环发生时字符串的长度都会发生变化。

According to the VB.NETdocumentation:

根据VB.NET文档:

If you change the value of counterwhile inside a loop, your code might be more difficult to read and debug. Changing the value of start, end, or stepdoesn't affect the iteration values that were determined when the loop was first entered.

如果您counter在循环内更改while的值,您的代码可能更难以阅读和调试。改变的值startendstep不影响被当首次进入循环确定的迭代值。

So, the value of To 10 - stringValue.Lengthis evaluated once and reused until the loops exit.

因此, 的值To 10 - stringValue.Length被评估一次并重复使用直到循环退出。

However, look at c#'s for statement

但是,看看c# 的 for 语句

If the for_conditionis not present or if the evaluation yields true, 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 the for_iterator, if any, are evaluated in sequence, and then another iteration is performed, starting with evaluation of the for_conditionin the step above.

如果for_condition不存在或者如果评估产生true,则控制转移到嵌入式语句。当和 if 控制到达嵌入语句的终点时(可能来自执行 continue 语句), 的表达式(for_iterator如果有)将按顺序计算,然后执行另一次迭代,从for_condition步骤中的 计算开始以上。

Which basically means that the condition ; i <= 10 - stringValueLength;is evaluated again each time.

这基本上意味着; i <= 10 - stringValueLength;每次都会再次评估条件。

So, as you saw, if you want to replicate the code, you need to declare the final counter in c# before starting the loop.

因此,如您所见,如果要复制代码,则需要在开始循环之前在 c# 中声明最终计数器。

回答by Maxime Recuerda

In order to make the example more understandable, I will convert both for loopsinto C#while loops.

为了使示例更易于理解,我将两个for 循环都转换为C#while 循环

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#

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.NETcaches the maximum value for i, but C#recomputes it every time.

VB.NET缓存 的最大值i,但C#每次都重新计算它。

回答by C Robinson

Because the forin VB is a different semantic than the forin C# (or any other C-like language)

因为forVB 中的语义与forC#(或任何其他类似 C 的语言)中的语义不同

In VB, the forstatement is specifically incrementing a counter from one value to another.

在 VB 中,该for语句专门将计数器从一个值递增到另一个值。

In C, C++, C#, etc., the forstatement simply evaluates three expressions:

在 C、C++、C# 等中,该for语句只计算三个表达式:

  • The first expression is customarily an initialization
  • The second expression is evaluated at the start of each iteration to determine whether the terminal condition has been met
  • The third expression is evaluated at the end of each iteration, which is customarily an incrementer.
  • 第一个表达式通常是一个初始化
  • 在每次迭代开始时计算第二个表达式以确定是否满足终止条件
  • 第三个表达式在每次迭代结束时计算,通常是一个增量器。

In VB, you mustsupply a numeric variable which can be tested against a terminal value and incremented on each iteration

在 VB 中,您必须提供一个数字变量,该变量可以针对终端值进行测试并在每次迭代时递增

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.

在C、C++、C#等中,这三个表达式的约束最小;条件表达式的计算结果必须为真/假(或 C、C++ 中的整数零/非零)。您根本不需要执行初始化,您可以在任何值范围内迭代任何类型,在复杂结构上迭代指针或引用,或者根本不迭代任何东西。

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.

所以,在 C# 等中,条件表达式必须在每次迭代时完全求值,但在 VB 中,迭代器的终值必须在开始时求值,不需要再次求值。