对于条件 VB.NET 与 C#
本文关键字:VB NET 条件 于条件 | 更新日期: 2023-09-27 17:55:59
C#:
static class Module1
{
public static void Main()
{
for (index = 1; index <= GetCount(); index++) {
Console.WriteLine("For {0}", index);
}
Console.ReadKey();
}
public static int GetCount()
{
Console.WriteLine("GetCount");
return 10;
}
}
结果(C# 重新检查条件):
GetCount
For 1
GetCount
For 2
GetCount
For 3
GetCount
For 4
GetCount
For 5
GetCount
For 6
GetCount
For 7
GetCount
For 8
GetCount
For 9
GetCount
For 10
GetCount
VB.NET
Module Module1
Sub Main()
For index = 1 To GetCount()
Console.WriteLine("For {0}", index)
Next
Console.ReadKey()
End Sub
Public Function GetCount() As Integer
Console.WriteLine("GetCount")
Return 10
End Function
End Module
结果(VB.NET 不重新检查条件):
GetCount
For 1
For 2
For 3
For 4
For 5
For 6
For 7
For 8
For 9
For 10
a) 为什么 VB.NET 不遵守每次迭代时重新检查 For 条件的"规则"?
b) 有没有办法强制 VB 重新检查此条件?
C# 和 VB.NET 是不同的语言,类似的关键字可以有不同的语义。
来自For ... Next
文档(我的强调):
当
For...Next
循环启动时,Visual Basic 会计算start
、end
和step
。这是它唯一一次评估这些值。
从 C# 规范的第 8.8.3 节(同上):
当控件到达嵌入语句的终点(可能来自继续语句的执行)时,将按顺序计算 for-iterator 的表达式(如果有),然后执行另一个迭代,从上述步骤中对 for 条件的计算开始。
如果您确实想每次都强制检查条件,VB.NET 提供了极其灵活的 Do ...循环,可以具有 While 或 till 条件,在循环的开始或结束时运行。使用该语句,每次都会评估循环条件。
while(condition)
在 VB.NET 中实现相同的效果。
这是编译器的区别。 VB.NET 编译器的行为不同。
如果在 VB.NET 上使用反射器,则会看到以下 C# 反射代码:
[STAThread]
public static void Main()
{
int VB$t_i4$L0 = GetCount();
for (int index = 1; index <= VB$t_i4$L0; index++)
{
Console.WriteLine("For {0}", index);
}
Console.ReadKey();
}
这是 IL 代码(注 IL_002):
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 47 (0x2f)
.maxstack 2
.locals init ([0] int32 index,
[1] int32 VB$t_i4$L0,
[2] int32 VB$CG$t_i4$S0)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: call int32 ConsoleApplication2.Module1::GetCount()
IL_0007: stloc.1
IL_0008: stloc.0
IL_0009: br.s IL_0021
IL_000b: ldstr "For {0}"
IL_0010: ldloc.0
IL_0011: box [mscorlib]System.Int32
IL_0016: call void [mscorlib]System.Console::WriteLine(string,
object)
IL_001b: nop
IL_001c: nop
IL_001d: ldloc.0
IL_001e: ldc.i4.1
IL_001f: add.ovf
IL_0020: stloc.0
IL_0021: ldloc.0
IL_0022: ldloc.1
IL_0023: stloc.2
IL_0024: ldloc.2
IL_0025: ble.s IL_000b
IL_0027: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_002c: pop
IL_002d: nop
IL_002e: ret
} // end of method Module1::Main
而对于 C# 代码,它是不同的(检查是否在循环内):
.method public hidebysig static void Main() cil managed
{
.entrypoint
// Code size 50 (0x32)
.maxstack 2
.locals init ([0] int32 index,
[1] bool CS$4$0000)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: br.s IL_001c
IL_0005: nop
IL_0006: ldstr "For {0}"
IL_000b: ldloc.0
IL_000c: box [mscorlib]System.Int32
IL_0011: call void [mscorlib]System.Console::WriteLine(string,
object)
IL_0016: nop
IL_0017: nop
IL_0018: ldloc.0
IL_0019: ldc.i4.1
IL_001a: add
IL_001b: stloc.0
IL_001c: ldloc.0
IL_001d: call int32 Module1::GetCount()
IL_0022: cgt
IL_0024: ldc.i4.0
IL_0025: ceq
IL_0027: stloc.1
IL_0028: ldloc.1
IL_0029: brtrue.s IL_0005
IL_002b: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_0030: pop
IL_0031: ret
} // end of method Module1::Main
VB.NET for 循环的工作方式与 C# 循环不同。它说从这个值到那个值。"该值"被评估一次。
C#基本上是for('initialise stuff';'conditional break stuff';'incremental stuff')
的,它每次都计算"条件中断的东西"。使用 C# 中的简单 for 循环,它看起来与 VB 循环相同,但它(如您所发现的)工作方式不同。
原因是 VB For
可以在 C# 中转换为类似这样的东西:
int count = GetCount();
for (index = 1; index <= count; index++)
{
}
或者,使用 LINQ 类似于 VB:
foreach(int i in Enumerable.Range(1,GetCount())
{
}
在这两种情况下(以及在VB版本中),GetCount()
被调用一次,因此只调用一次Console.WriteLine("GetCount")
。
好吧,简短的回答是它们是不同的语言,他们对这个关键字的看法略有不同。
在 C# 中,迭代将继续,直到终止条件的计算结果为 false,并在每次迭代时对其进行计算。
在 VB.NET 中,我们对每个整数值从开始到结束迭代一次(前提是 step 关键字不存在),然后停止。结束在开始时被评估一次,仅此而已。
可以使用 Do 循环更接近 VB.NET 中的 C# 行为类型。
VB.NET For..循环只需要调用该方法一次。它存储该值并在每次循环迭代时对其进行检查。其中 c# for 循环在每次迭代时调用它。您可以将 c# 版本视为一种花哨的语法:
index = 1;
while(index <= GetCount()) {
Console.WriteLine("For {0}", index);
index++;
}
如果你尝试用 c# 和 VB.NET 编写它,它们的操作将相同。
正如其他人所说,VB.Net 和C#是不同的语言,因此可能会发生这些差异。
如果要在 VB.Net 中强制重新评估循环条件,则必须将 For 循环重写为 While 循环