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

(这更像是一个注释,但需要太多代码才能将其保留为一个。)

反射器确实显示正在发生的事情:

<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没有得到这种处理。

还是不知道为什么?对我来说似乎是一个错误。如果我在一天左右没有得到合理的“借口”(:-)),我会把它放在 Connect 上。(有人可以确认 .NET 4.5 VB11 的性能相同吗?)

于 2012-11-07T13:05:51.907 回答
2

来自 MSDN(重点是我的):

[...]编译器基本上做了什么,当它进入一个包含提升变量的新范围时,编译器将检查是否已经存在闭包实例;如果是这样,编译器将创建一个新的闭包实例并从前一个闭包中重置变量的值。

请注意,编译器仅执行上述检查是否在生成闭包的函数中检测到循环或 GoTo

关联

于 2012-11-07T11:49:40.497 回答