2

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 ステートメントの実装方法のバグなのか、それとも何かが欠けていてこれが予期される動作なのかということです。

4

0 に答える 0