简体   繁体   English

对于条件VB.NET与C#

[英]For Condition VB.NET vs C#

C#: 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;
    }
}

Result (C# rechecks the condition): 结果(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 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

Result (VB.NET does not recheck the condition): 结果(VB.NET不重新检查条件):

GetCount
For 1
For 2
For 3
For 4
For 5
For 6
For 7
For 8
For 9
For 10

a) Why doesn't VB.NET respect the "rule" of the recheck the For condition on each iteration? a) 为什么 VB.NET不遵循每次迭代重新检查For条件的“规则”?
b) Is there a way to force VB to re-check this condition? b) 有没有办法强制 VB重新检查这种情况?

C# and VB.NET are different languages, and similar keywords can have different semantics. C#和VB.NET是不同的语言,类似的关键字可以有不同的语义。

From the docs for For ... Next (my emphasis) : 来自For ... Next (我的重点) 的文档

When a For...Next loop starts, Visual Basic evaluates start , end , and step . For...Next循环启动时,Visual Basic会评估startendstep This is the only time it evaluates these values . 这是它评估这些值的唯一时间

From section 8.8.3 of the C# specification (ditto): 从C#规范的第8.8.3节(同上):

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-condition in the step above. 当控制到达嵌入语句的结束点时(可能来自执行continue语句),for-iterator的表达式(如果有的话)按顺序计算,然后执行另一次迭代, 从评估在上面的步骤中的条件

If you do want to force the condition to be checked every time, VB.NET offers the extremely flexible Do ... Loop which can have a While or an Until condition, operating at the start or the end of the loop. 如果您确实希望每次都强制检查条件,VB.NET提供极其灵活的Do ...循环,它可以具有While until条件,在循环的开始结束时运行。 With that statement, the loop condition is evaluated every time round. 这种说法,循环条件进行评估,每次轮。

You can achieve the same effect in VB.NET using while(condition) . 使用while(condition)可以在VB.NET中实现相同的效果。


This is the difference with the compiler . 这与编译器有所不同。 VB.NET compiler just behaves differently. VB.NET编译器只是表现不同。

if you use reflector on the VB.NET one, you see this C# reflected code: 如果你在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();
}

And here is the IL code (note IL_002): 这是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

While for the C# code it is different (check is inside the loop): 虽然对于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

The VB.NET for-loop doesn't work the same way as the C# one. VB.NET for循环的工作方式与C#的工作方式不同。 It says go from this value, to that value. 它说从这个值到该值。 The 'that value' is evaluated once. “那个值”被评估一次。

The C# one is basically for('initialise stuff';'conditional break stuff';'incremental stuff') , it evaluates the 'conditional break stuff' each time. C#one基本上for('initialise stuff';'conditional break stuff';'incremental stuff') ,它每次都会评估'条件中断东西'。 With a simple for-loop in C# it looks the same as the VB one, but it is (as you've found) working differently. 在C#中使用简单的for循环看起来和VB一样,但它(正如你所发现的)工作方式不同。

The reason is that the VB For can be translated into something like this in C#: 原因是VB For可以在C#中翻译成这样的东西:

int count = GetCount();
for (index = 1; index <= count; index++)
{
}

or, using linq to resemble VB: 或者,使用linq类似VB:

foreach(int i in Enumerable.Range(1,GetCount())
{
}

In both cases (and in VB version) GetCount() is called once, hence one call to Console.WriteLine("GetCount") only. 在这两种情况下(以及在VB版本中), GetCount()被调用一次,因此只调用一次Console.WriteLine("GetCount")

Well, the short answer is they're different languages and they have slightly different takes on this keyword. 嗯,简短的回答是它们是不同的语言,它们对此关键字的看法略有不同。

In the C#, iteration continues until the termination condition evaluates to false, and it's evaluated on each iteration. 在C#中,迭代继续,直到终止条件计算为false,并在每次迭代时对其进行求值。

In VB.NET, we iterate one time for each integer value from Start to End (provided the step keyword is not present) and then stop. 在VB.NET中,我们为从Start到End的每个整数值迭代一次(假设步骤关键字不存在)然后停止。 End is evaluated once at the beginning and that's it. 结束在开始时评估一次,就是这样。

You could get closer to the C# type of behavior in VB.NET using a Do loop. 您可以使用Do循环更接近VB.NET中的C#行为类型。

the VB.NET For..To loop only needs to call the method once. VB.NET For..To循环只需要调用一次方法。 It stores that value and checks it on each loop iteration. 它存储该值并在每次循环迭代时检查它。 Where the c# for loop calls it on each iteration. c#for循环在每次迭代时调用它。 You can think of the c# version a fancy syntax for: 您可以将c#版本视为一种精美的语法:

index = 1;
while(index <= GetCount()) {
  Console.WriteLine("For {0}", index);
  index++;
}

And if you try to write that in both c# and VB.NET they will operate the same. 如果您尝试在c#和VB.NET中编写它们,它们将以相同的方式运行。

As others have said, VB.Net and C# are different languages so these kind of differences can happen. 正如其他人所说,VB.Net和C#是不同的语言,因此可能会出现这种差异。

If you want to force re-evaluation of the loop condition in VB.Net, you have to rewrite the For loop as a While loop 如果要在VB.Net中强制重新评估循环条件,则必须将For循环重写为While循环

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM