Lambda Closures Handle Event Handlers’ State

Subscribing to an event with a method that requires state is a pain because it often requires a class to be created to hold that state. Fortunately we can use a lambda expression to have the compiler create that state for us instead.

It is not an uncommon scenario to have an event handler that will do something with some specific data when an event fires. An example I had lately was a mail helper that only would send the email after the Entity Framework DbContext successfully has executed SaveChanges(). That way I knew that the database was properly updated with the state that the mail was indeed sent. Everything was wrapped in a transaction too, so if the mail failed to send the entire transaction was rolled back, undoing the database changes.

Anyway, that code could be a pain to write. I would have to create a separate object that held a reference to the e-mail to send and subscribe a method of that class to the DbContext’s SavingChanges() event (ok, it’s a bit more complicated than that to get to the SavingChanges event, but that’s another topic). Instead I used a lambda expression that creates a closure that automatically captures the required variable.

For a really simple example, I’ll show a helper function that schedules an asynchronous push of a specific number to a Stack after a timeout. The code is deliberately not thread safe regarding the Stack to not clutter up the use of the lambda.

public static void Run(Stack<int> result)
{
    ScheduleAdd(result, number: 1, timeoutms: 2);
    ScheduleAdd(result, number: 2, timeoutms: 1);
 
    System.Threading.Thread.Sleep(20);
}
 
private static void ScheduleAdd(Stack<int> stack, int number, int timeoutms)
{
    var t = new Timer(timeoutms) { AutoReset = false };
 
    t.Elapsed += (object sender, ElapsedEventArgs eventArgs) => stack.Push(number);
    t.Enabled = true;
}

The event handler has to know what number to push. Using the lambda, variable capturing handles it. At a glance, this doesn’t look complicated but it is. The variable number is used inside the event handler. That variable number is an argument to the ScheduleAdd function. When the event fires and the event handler runs, it’s a long time (at least for a computer) since the ScheduleAdd function returned so the number variable has gone out of scope and is gone. How does the event handler know what number to push? Even more complicated, we’re scheduling two different adds, so each instance of the event handler has to keep track of its own number.

The answer is that the compiler creates a small helper class for us, instantiating an object of that class for each time the lambda is used. After the compiler has done its magic there is indeed a small helper object that is used to subscribe to the event. The good thing is that the compiler writes it automatically, meaning less code to maintain.

Variable capturing in closures is a bit of magic, but it is really powerful magic that can be utilized in many ways to write less code that’s on the same time more readable.

  • Leave a Reply

    Your name as it will be displayed on the posted comment.
    Your e-mail address will not be published. It is only used if I want to get in touch during comment moderation.
    Your name will be a link to this address.
Software Development is a Job – Coding is a Passion

I'm Anders Abel, a systems architect and developer working for Kentor in Stockholm, Sweden.

profile for Anders Abel at Stack Overflow, Q&A for professional and enthusiast programmers

The complete code for all posts is available on GitHub.

Popular Posts

Archives

Series

Powered by WordPress with the Passion for Coding theme.