When Events Go Bad

Yesterday, I discovered the dark, evil, brooding side to using lambdas to hook up events, even though they look so cool. Here’s an example:

public void GetCustomerOrders(string storeId)
{
    Proxy.DocumentDownloadCompleted += (data) => this.HandleCustomerOrders(data);
    Proxy.GetXML("customerorderservice.svc/customerorders/" + storeId);
}

All well and good, that works like a champ. Usually. As long as you don’t want to ever unhook the event.

But let’s say you want to do something like this when the response comes back.

private void HandleCustomerOrders(Stream data)
{
    base.Proxy.DocumentDownloadCompleted -= this.HandleCustomerOrders;

    // Do something interesting here.
}

Maybe you want to do this because you have multiple handlers hooked up to the same event and in reality, you only want to handle one at a time. The problem here is that the unhooking does nothing here because that HandleCustomerOrders isn’t actually the function handling the event. When the compiler finds a lambda, it does one of two things. If there are variables that the lambda closes around, the compiler creates an anonymous private class on the enclosing class. If there aren’t any variables to close around, the compiler creates a new anonymous function on the current class. In either case, the event you think you are hooking up to is actually being hooked up to the created anonymous function. When you try to unhook, nothing happens because it was never hooked up to begin with.

In cases where you want to have the ability to unhook from events, you can’t use lambdas to hook up your events. You have to be a bit more old school, if less hip and do this.

public void GetCustomerOrders(string storeId)
{
    base.Proxy.DocumentDownloadCompleted += this.HandleCustomerOrders;
    base.Proxy.GetXML("customerorderservice.svc/customerorders/1");
}

By doing that, you will be able to unhook the events when the response happens. This public service announcement brought to you by the lost 2 hours of my dumbfounded life yesterday afternoon.

Closures in Clojure and C#

So one of the ways I learn a new language is to take new things from the new language and port them back into the old, familiar one. Eventually, I’ll port an entire application (even though that app may be very small) from the old to the new. I find that I learn things much better this way. Tonight’s example is closures in Clojure and C#.

In Clojure, you can do this:

(defn make-greeter [greeting-prefix]
(fn [username] (str greeting-prefix ", " username)))

This basically creates a closure around greeting-prefix that can be used to create custom ways to greet people. For example

(defn hello-greeting (make-greeter "Hello"))

creates a closure than can be called with

(hello-greeting "Brett")

and get “Hello, Brett”

You can do the same thing in C# though it’s a little more work because it’s a statically typed language. In C#, a small console app looks like this:

namespace ClosureToy
{
    class Program
    {
        static void Main(string[] args)
        {
            //Class1 one = new Class1();
            Func hello = MakeGreeter("Hello");
            Func aloha = MakeGreeter("Aloha");

            Console.WriteLine(hello("brett"));
            Console.WriteLine(aloha("brett"));
            Console.Read();
        }

        static Func MakeGreeter(string greetingPrefix)
        {
            return (username) => String.Format("{0}{1}{2}", greetingPrefix, ", ", username); ;
        }
    }
}

The MakeGreeter function is a closure around greetingPrefix that allows you to create custom greeter functions on the fly. Essentially, it’s doing the same thing as the Clojure code as you can see from the main body of the console app where it creates two greeter functions on the fly, one that says hello and one that says aloha. Closures make it easier to abstract common pieces of code in your applications.