gpt4 book ai didi

VB.Net - "With"和闭包不混合

转载 作者:行者123 更新时间:2023-12-04 11:30:54 40 4
gpt4 key购买 nike

只是想我会分享这个以防其他人遇到这个问题。
我今天做了类似的事情,我花了一段时间才弄清楚为什么这会导致运行时出现问题。

这段代码:

Public Class foo
Public bar As String = "blah"
End Class

Public Sub DoInline()
Dim o As New foo
Dim f As Func(Of String)
With o
f = Function() .bar
End With
Try
Console.WriteLine(f.DynamicInvoke())
Catch ex As Reflection.TargetInvocationException
Console.WriteLine(ex.InnerException.ToString)
End Try
End Sub

抛出 NullReferenceException。似乎 With 正在使用闭包作为其临时存储,并且在“End With”处,它将闭包的变量设置为 Nothing。

这是 RedGate Reflector 中的代码:
Public Shared Sub DoInline()
Dim o As New foo
Dim $VB$Closure_ClosureVariable_7A_6 As New _Closure$__1
$VB$Closure_ClosureVariable_7A_6.$VB$Local_VB$t_ref$L0 = o
Dim f As Func(Of String) = New Func(Of String)(AddressOf $VB$Closure_ClosureVariable_7A_6._Lambda$__1)
$VB$Closure_ClosureVariable_7A_6.$VB$Local_VB$t_ref$L0 = Nothing
Try
Console.WriteLine(RuntimeHelpers.GetObjectValue(f.DynamicInvoke(New Object(0 - 1) {})))
Catch exception1 As TargetInvocationException
ProjectData.SetProjectError(exception1)
Console.WriteLine(exception1.InnerException.ToString)
ProjectData.ClearProjectError
End Try
End Sub

请注意
$VB$Closure_ClosureVariable_7A_6.$VB$Local_VB$t_ref$L0 = Nothing 

我真正可以问的唯一“问题”是;这是一个错误还是一个奇怪的设计决定,由于某种原因我没有看到。
从现在开始,我几乎将避免使用“With”。

最佳答案

这种行为是“设计使然”,是由 With 的一个经常被误解的细节造成的。陈述。
With语句实际上将表达式作为参数而不是直接引用(即使它是最常见的用例之一)。语言规范的第 10.3 节保证表达式传递到 With块仅被评估一次并且可用于执行 With陈述。

这是通过使用临时文件来实现的。所以在执行 .Member 时表达在 With 中声明您访问的不是原始值,而是指向原始值的临时值。它允许其他有趣的场景,例如以下内容。

Dim o as New Foo
o.bar = "some value"
With o
o = Nothing
Console.WriteLine(.bar) ' Prints "some value"
End With

这是有效的,因为在 With 里面您不在操作的声明 o而是临时指向原始表达式。这个临时文件只能保证在 With 的生命周期内有效声明,因此是 Nothing d 最后出来。

在您的示例中,闭包正确捕获了临时值。因此,当它在 With 之后执行时语句完成临时是 Nothing并且代码适本地失败了。

关于VB.Net - "With"和闭包不混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4054837/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com