我今天遇到了一个关于 lambda 函数闭包和 VBWith
语句的交互的非常有趣的怪癖。这是一个简短的代码片段来演示这个问题(我试图让它尽可能地小),然后是我认为问题所在的概述:
Module Module1
Sub Main()
Dim someList = New List(Of String),
myInvoker As Invoker
With someList
Dim listFiller = Sub()
.Add("Hello") '<- This is where the problem is
End Sub
myInvoker = New Invoker(listFiller)
End With
myInvoker.Invoke()
Console.WriteLine(String.Join(",", someList))
Console.ReadKey()
End Sub
End Module
'This is just an object that accepts a delegate and invokes it when told to
Public Class Invoker
Public Delegate Sub ArbitraryDelegate()
Private _ArbitraryCallBack As ArbitraryDelegate
Public Sub Invoke()
_ArbitraryCallBack.Invoke()
End Sub
Public Sub New(arbitraryCallback As ArbitraryDelegate)
_ArbitraryCallBack = arbitraryCallback
End Sub
End Class
基本上,我正在创建一个引用类型的实例(List(Of String)
在这种情况下是 a,但它可以是任何东西),将它存储在一个变量中,然后在With
语句中使用它。当我创建一个 lambda 函数来访问这个对象的方法时,问题就出现了.Add
。一旦我创建了 lambda 函数,我将它传递给某个外部对象,以便稍后调用。
不幸的是,当外部对象试图调用给定的 lambda 函数时,它会遇到System.NullReferenceException
,因为 lambda 表达式(无论出于何种原因)未能关闭subList
。如果我明确写subList.Add("Hello")
,它会再次起作用。据我所知,这两种情况的行为应该相同,因为以.Add
.
我的问题是,这是否是 With 语句实现方式的错误,或者我是否遗漏了某些东西,这是预期的行为。