2012-11-26 6 views
10

Ich habe so etwas wie dies:VB.NET boolean erhält seinen Standardwert in Schleife nicht?

For i = 1 To 4 
     Dim x As Boolean 
     If i < 3 Then x = True 
     Console.WriteLine(x) 
Next 

Gibt mir: Wahre Wahre Wahre Wahre

und diese

For i = 1 To 4 
     Dim x As Boolean = False 
     If i < 3 Then x = True 
     Console.WriteLine(x) 
Next 

mich Gibt: Wahre Wahr Falsch Falsch

Sind sie nicht beide, um mir das zweite Ergebnis zu geben? The MSDN article sagt, dass der Standardwert von Boolean False ist.

Ist es ein Fehler oder fehlt mir etwas?

Antwort

13

Danke für die sehr interessante Frage. Ich nahm den Beispielcode:

Module Module1 

    Sub Main() 
     Test1() 
     Test2() 
     Console.ReadKey() 
    End Sub 

    Public Sub Test1() 
     For i = 1 To 4 
      Dim x As Boolean 
      If i < 3 Then x = True 
      Console.WriteLine(x) 
     Next 
    End Sub 

    Public Sub Test2() 
     For i = 1 To 4 
      Dim x As Boolean = False 
      If i < 3 Then x = True 
      Console.WriteLine(x) 
     Next 
    End Sub 
End Module 

Und warf einen Blick auf die erzeugte IL über ILSpy:

Test1()

.method public static 
     void Test1() cil managed 
    { 
     // Method begins at RVA 0x2120 
     // Code size 33 (0x21) 
     .maxstack 2 
     .locals init (
      [0] int32 i, 
      [1] bool x, 
      [2] bool VB$CG$t_bool$S0, 
      [3] int32 VB$CG$t_i4$S0 
     ) 

     IL_0000: nop 
     IL_0001: ldc.i4.1     
     IL_0002: stloc.0      // put 1 on top of stack 
     // loop start (head: IL_0003) 
      IL_0003: ldloc.0     // load i on top of stack 
      IL_0004: ldc.i4.3     // load 3 on top of stack 
      IL_0005: clt      // compare if 0 is less than 3 
      IL_0007: stloc.2     
      IL_0008: ldloc.2 
      IL_0009: brfalse.s IL_000d   // if i >= 3, jump to IL_000d 

      IL_000b: ldc.i4.1     // load true onto stack 
      IL_000c: stloc.1     // set x = true 

      IL_000d: ldloc.1     // load x onto stack 
      IL_000e: call void [mscorlib]System.Console::WriteLine(bool) // print x 
      IL_0013: nop 
      IL_0014: nop 
      IL_0015: ldloc.0     // load i onto stack 
      IL_0016: ldc.i4.1     // load 1 onto stack 
      IL_0017: add.ovf     // add i + 1 
      IL_0018: stloc.0     // set i = i + 1 
      IL_0019: ldloc.0     // load i 
      IL_001a: ldc.i4.4     // load 4 
      IL_001b: stloc.3     // store 4 in iterator variable 
      IL_001c: ldloc.3     // load 4 from iterator variable 
      IL_001d: ble.s IL_0003    // if i <= 4, go to beginning of loop 
     // end loop 
     IL_001f: nop 
     IL_0020: ret 
    } // end of method Module1::Test1 

Test2()

 .method public static 
     void Test2() cil managed 
    { 
     // Method begins at RVA 0x2150 
     // Code size 35 (0x23) 
     .maxstack 2 
     .locals init (
      [0] int32 i, 
      [1] bool x, 
      [2] bool VB$CG$t_bool$S0, 
      [3] int32 VB$CG$t_i4$S0 
     ) 

     IL_0000: nop 
     IL_0001: ldc.i4.1     // load 1 onto stack 
     IL_0002: stloc.0     // set i = 1 
     // loop start (head: IL_0003)  
      IL_0003: ldc.i4.0    // load 0 onto stack 
      IL_0004: stloc.1    // set x = false 
      IL_0005: ldloc.0    // load i onto stack 
      IL_0006: ldc.i4.3    // load 3 onto stack 
      IL_0007: clt     // compare i to 3 
      IL_0009: stloc.2    // store result in iterator variable 
      IL_000a: ldloc.2    // load iterator variable 
      IL_000b: brfalse.s IL_000f  // if i >= 3, jump to IL_00f 

      IL_000d: ldc.i4.1    // load 1 onto stack 
      IL_000e: stloc.1    // set x = true 

      IL_000f: ldloc.1    // load x onto stack 
      IL_0010: call void [mscorlib]System.Console::WriteLine(bool) // print x 
      IL_0015: nop    
      IL_0016: nop 
      IL_0017: ldloc.0    // load i onto stack 
      IL_0018: ldc.i4.1    // load 1 onto stack 
      IL_0019: add.ovf    // add i + 1 
      IL_001a: stloc.0    // set i = i + 1 
      IL_001b: ldloc.0    // load i onto stack 
      IL_001c: ldc.i4.4    // load 4 onto stack 
      IL_001d: stloc.3    // store 4 into iterator variable 
      IL_001e: ldloc.3    // load 4 from iterator variable 
      IL_001f: ble.s IL_0003   // if i <= 4, go to beginning of loop 
     // end loop 
     IL_0021: nop 
     IL_0022: ret 
    } // end of method Module1::Test2 

Was sagt uns das? ist, dass, obwohl Sie x in der Schleife deklarieren (Dim x as Boolean) und (Dim x as boolean = False), die eigentliche Deklaration der Variablen außerhalb der Schleife passiert.

Da Sie Ihrer Variablen innerhalb der Schleife in Test2 einen Standardwert geben, setzt sie den Wert zu Beginn jeder Iteration auf False. Da Sie in der Schleife Test1 keinen Wert an x ​​zuweisen und nur einmal außerhalb der Schleife deklariert wird, behält es den Wert, den es in der vorherigen Iteration hatte.

4

Die Variable x wird nicht bei jeder Iteration der Schleife initialisiert - nur die erste. Beispiel 1 ist die gleiche wie

Dim x As Boolean 
For i = 1 To 4 
     If i < 3 Then x = True 
     Console.WriteLine(x) 
Next 

Wenn Sie es sehen diese Art und Weise ist es sinnvoll, warum Sie mit True True True True Ende, weil Sie es auf True auf dem ersten Durchgang durch die Schleife setzen und es gibt nichts, setzt es auf False.

Beispiel 2 ist die gleiche wie

Dim x As Boolean 
For i = 1 To 4 
     x = False 
     If i < 3 Then x = True 
     Console.WriteLine(x) 
Next 

Sicher nicht intuitiv ist, aber das ist das, was der Compiler tut

+0

Das ist korrekt, ich habe die generierte IL in meiner obigen Antwort gepostet, die Ihre Behauptung bestätigt. –