rss

Anonymous methods make elegant proxies

2

Category : C#, Design

Just stumbled on that fact some times ago.

Well at first some background, with C# 2.0 appeared a new usage of the keyword delegate in form of anonymous functions or closure (although they aren’t really new in themselves).

One of the most useful feature of anonymous method is the concept of ‘variable capture’ but even though it proves useful here it’s not the main part of the pattern.

Together with this C# 2.0′s anonymous method feature, the compiler also get enhanced to allow delegate type inference for variable and parameter. Indeed before C# 2.0 you had to explicitly initialize a delegate in order to use it :

private delegate void Func(int someInt);
Func func = new Func(MyMethod);

With C# 2.0 this dummy syntax is removed and one can write the more concise :

private delegate void Func(int someInt);
Func func = MyMethod;

But what this had to do with our subject ? Well you may know it or not but when you create anonymous method using only the delegate keyword (i.e. without any definition of parameters) the compiler automatically adapt the signature of the anonymous method to the underlying delegate. In other word it’s a cheap way to make Proxy (where Proxy refers to the design pattern that might be described as : « Providing an interface to a class which doesn’t implement it natively »).

How can we use this feature then ? Say you want to run a method on a dedicated thread (like the target toolkit’s mainloop in Circ) then this method (that we will call StartPresentation) might want some information to initialize the presentation like, for example, a reference to the main controller, the title for the Window etc… (which used to be the case in previous version of Circ).

Problem : the Thread class allow only a method which signature correspond to the ThreadStart delegate (defined as public delegate void ThreadStart();) in its constructor. Unfortunately, in our case, it doesn’t correspond the signature of our StartPresentation method. Nonetheless, thanks to some delegate magic, you can circumvent this limitation with this pattern :

public void InitializePresentation()
{
    // Well usually the MainControl isn't defined
    // there but it shows closure's ability to
    // capture outer variables
    MainControl ctrl = new MainControl();
    Thread thread = new Thread(delegate {
            StartPresentation(ctrl, "Window's Title);
    });
    thread.Start();
}

And here you go ! The anonymous method signature is automatically mapped to the one of the ThreadStart’s delegate by the compiler without any developer intervention.

Comments (2)

That last example is not great – when you omit the parameter list on the anonymous method, the overloading is ambiguous.

(ThreadStart and ParameterizedThreadStart both match)

Or does the Mono C# compiler have some notion of a « best » match, that the Microsoft compiler does not?

Back in the day it was working. Now it’s not the case anymore for that sample. I will update when I have time.

Meanwhile, as another example, this pattern is also useful with Gtk# Application.Invoke(EventHandler) when you want to execute some piece of code not contained in a EventHandler-style method on the GUI thread.

Post a comment