With
今日、ラムダ関数クロージャーと VB ステートメントの相互作用に関して、かなり興味深い癖に出会いました。問題を示す短いコード スニペットを次に示します (可能な限り最小限に抑えようとしました)。次に、問題と思われるものの概要を示します。
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
ステートメントで使用しています。を使用してこのオブジェクトのメソッドにアクセスするラムダ関数を作成すると、問題が発生します.Add
。ラムダ関数を作成したら、それを何らかの外部オブジェクトに渡して、後で呼び出します。
残念ながら、外部オブジェクトが指定されたラムダ関数を呼び出そうとするとSystem.NullReferenceException
、ラムダ式が (何らかの理由で) を閉じることができなかったため、 に遭遇しsubList
ます。明示的に書くsubList.Add("Hello")
と、再び機能します。で始まる行にはあいまいな解釈がないため、私が見る限り、2 つのシナリオは同等に動作するはず.Add
です。
私の質問は、これが With ステートメントの実装方法のバグなのか、それとも何かが欠けていてこれが予期される動作なのかということです。