Freigeben über


Closures in VB Part 2: Method Calls

For previous articles in this series, please see

This part of the series will focus on how method calls are handled in closures.  As stated in the previous article, the purpose of closures is to allow all operations inside a lambda or query expression that would normally be available inside the function or sub.  To do this closures often need to capture (or lift) relevant variables from the function into the generated class.

There are 2 types of methods and method calls that closures have to handle. 

  1. Method calls to a shared method or methods on modules.
  2. Method calls to instance members of a class

Scenario #1

Below is an example of a method call inside a lambda expression for scenario #1. 

 Module M1

    Function MyValue() As Integer
        Return 42
    End Function

    Sub Example1()
        Dim x = 5
        Dim f = Function() x + MyValue()
    End Sub

End Module

Here we are calling a module method inside a lambda.  Module Methods or Shared methods can be called from anywhere because they require no specific variable for the call.  This requires no special work from closures as the call can just be made naturally.

     Class Closure
        Private x As Integer

        Function Lambda_f() As Integer
            Return x + M1.MyValue
        End Function
    End Class

Scenario #2

Calling an instance method is more difficult than a shared method because it requires the referenc "Me".  If you don't type this specifically in code the VB Compiler will add it for you under the hood.  To make this work the closures code will also "lift" the variable "Me" in the same way that it lifts normal variables in a function. 

Calling a instance method inside a lambda expression is little difference than calling a member method on a variable used in a lambda.  The only difference is the variable is "Me".  For example

 Class C1
    Private m_myValue As Integer

    Function MyValue() As Integer
        Return m_myValue
    End Function

    Sub Example2()
        Dim x = 5
        Dim f = Function() x + MyValue()
    End Sub
End Class

In this case we need to access both "x" and "Me.MyValue()" from the closure.  The generated code will create space for both of these variables and the transformed code in Example2 will store both of the values.

 Class Closure
    Private x As Integer
    Private OriginalMe As C1

    Function Lambda_f()
        Return x + OriginalMe.MyValue()
    End Function
End Class
     Sub Example2()
        Dim c As New Closure
        c.x = 5
        c.OriginalMe = Me
        Dim f = New Func(Of Integer)(AddressOf c.Lambda_f)
    End Sub

As usual, the generated code is much uglier but this essentially what will be generated.  That wraps it up for method calls.  In the next part, I will discuss the variable liftetime and scoping issues that come into play with closures.

Comments

  • Anonymous
    May 05, 2007
    The comment has been removed

  • Anonymous
    May 08, 2007
    HaHa, I hadn't noticed my About page went blank.  I'll have to update that.   Anna's pretty good herself.  I can't believe she switched to the dark side.  

  • Anonymous
    May 23, 2007
    What happens in the following situation? Sub Example()  Dim x = 5  Dim f1 = Function() x  Dim f2 = Function() x End Sub Does 'x' get lifted into its own separate class, or does the lifing happen recursively? That is, a reference to the closure class for f1 is lifted into the closure class for f2.

  • Anonymous
    May 23, 2007
    In this situation you've only lifted a single variable therefore it will create a single closure class.  Each of the methods, f1 and f2, will end up as instance members on the created closure instance.   If you start lifting variables at different scopes then you will end up with nested closures and fun referencing issues.  That is coming up in the next part of this series.  And now that our current milestone is past us I may have time to write it :)

  • Anonymous
    May 25, 2007
    For previous articles in this series please see Part 1: Introduction Part 2: Method Calls Thus far in

  • Anonymous
    June 15, 2007
    For previous articles in this series please see Part 1: Introduction Part 2: Method Calls Part 3: Scope

  • Anonymous
    July 26, 2007
    For previous articles in the series please see Part 1: Introduction Part 2: Method Calls Part 3: Scope

  • Anonymous
    August 06, 2007
    For previous articles in this series please see ... Part 1: Introduction Part 2: Method Calls Part 3:

  • Anonymous
    August 06, 2007
    For previous articles in this series please see ... Part 1: Introduction Part 2: Method Calls Part 3