9

スコープを除いて、VB.NET での変数宣言の位置が重要ではないことを確認していました (この質問の場合)。それらがクロージャーに「持ち上げられた」ときに何が起こるかを確認する方がよいと思いました。私は仕様を読んでいませんが、これらの結果を説明することはできません:

Dim outer As Integer
For i = 1 To 2
 Dim inner As Integer
 Try
  Dim inner2 As Integer
  Do
   Dim inner3 As Integer
   Call Sub()
    Dim inner4 As Integer
    Console.WriteLine(outer & ", " & inner & ", " & inner2 & ", " & inner3 & ", " & inner4)
    outer = i
    inner = i
    inner2 = i
    inner3 = i
    inner4 = i
   End Sub()
  Loop Until True
 Finally
 End Try
Next

上記の出力:

0, 0, 0, 0, 0
1, 1, 0, 1, 0

inner4毎回リセットされるのは理にかなっていinnerXますinner2

4

2 に答える 2

2

MSDNから(私の強調):

[...]コンパイラが基本的に行うことは、リフトされた変数を含む新しいスコープに入ると、コンパイラはクロージャのインスタンスがすでに存在するかどうかを確認します。その場合、コンパイラーはクロージャーの新しいインスタンスを作成し、以前のクロージャーから変数の値をリセットします。

コンパイラは、クロージャが生成される関数でループまたはGoToを検出した場合にのみ、上記のチェックを実行することに注意してください。

リンク

于 2012-11-07T11:49:40.497 に答える
2

(これはコメントですが、1 つにまとめるにはコードが多すぎます。)

Reflector はが起こっているかを示します:

<STAThread> _
Public Shared Sub Main()
Dim e$__ As New _Closure$__1
Try 
    Dim e$__2 As New _Closure$__2
    Dim e$__3 As New _Closure$__3
    e$__3.$VB$Local_i = 1
    Do
        Dim e$__4 As _Closure$__4
        e$__4 = New _Closure$__4(e$__4)
        Try 
            Dim e$__5 As New _Closure$__5
            Do
                Dim e$__6 As _Closure$__6
                e$__6 = New _Closure$__6(e$__6)
                e$__6.$VB$NonLocal_$VB$Closure_ClosureVariable_8_5 = e$__5
                e$__6.$VB$NonLocal_$VB$Closure_ClosureVariable_6_4 = e$__4
                e$__6.$VB$NonLocal_$VB$Closure_ClosureVariable_6_6 = e$__3
                e$__6.$VB$NonLocal_$VB$Closure_ClosureVariable_4_4 = e$__2
                e$__6.$VB$NonLocal_$VB$Closure_ClosureVariable_2_B = e$__
                Dim e_ As VB$AnonymousDelegate_0 = New VB$AnonymousDelegate_0(AddressOf e$__6._Lambda$__1)
                e_.Invoke
            Loop While (0 <> 0)
        End Try
        e$__3.$VB$Local_i += 1
    Loop While (e$__3.$VB$Local_i <= 2)
End Try
End Sub

Try(これは、 の外側を含む私のコードに基づいていますFor。)

ここで、Forループ (前Doに設定されたループとして表示$VB$Local_i) と、クロージャーの前のインスタンスが渡された内部Do生成クロージャーを確認できますが、Tryその処理は行われません。

理由はまだわかりませんか?私にはバグのように見えます。1 日かそこらで妥当な「言い訳」が得られない場合 (:-))、Connect に投稿します。(誰かが.NET 4.5 VB11が同じことを実行することを確認できますか?)

于 2012-11-07T13:05:51.907 に答える