Anonymous Method is Not Closure

C# 2.0 has *tried* to embrace part of functional programming concept, the closure, and was implemented as anonymous method, which then evolved into Lambda Expression in C# 3.0. But why aren’t they closure? Does C# have true closure? Most people know the answer: NO. But few understand why. Despite its similar concept, there are some subtle differences between closure and anonymous method.

Stateful vs Stateless

The main difference between closure and anonymous method is that closure is stateful. A code is worth a thousand words:

string name = “World”;

 

HelloDelegate hello = delegate {

Console.WriteLine(“Hello, “ + name); };

 

name = “Sheep”;

hello();

A simple hello-world application, using a C# 2.0 anonymous method. What would the output be? Unlike other hello-world applications, this code will actually print “Hello, Sheep”!

But on closure, the same pseudocode will output “Hello, World”! A quick explanation is that a true closure preserves the lexical state when it is created. It indicates that the method is “closed” from its lexical environments, hence “closure”.

Whereas in C# anonymous type, the value of name when the delegate was created is NOT preserved, and the last value of name (“Sheep”) is used instead.

Instance State

This is another way to look at stateful characteristic of closure compared to anonymous method.

string name = “World”;

 

HelloDelegate hello = delegate {

       name += “!”;

       Console.WriteLine(“Hello, “ + name); };

 

HelloDelegate hello2 = delegate

{

       name += “!”;

       Console.WriteLine(“Hello2, “ + name);

};

 

hello();

hello();

hello();

hello2();

hello2();

hello2();

Console.WriteLine(“Finally: “ + name);

In C#, it will print this output:

Hello, World!

Hello, World!!

Hello, World!!!

Hello2, World!!!!

Hello2, World!!!!!

Hello2, World!!!!!!

Finally, World!!!!!!

But in Ruby’s closure, the result is:

Hello, World!

Hello, World!!

Hello, World!!!

Hello2, World!

Hello2, World!!

Hello2, World!!!

Finally, World

Note that in Ruby, each closure instance remembers its own ‘local-state’. A change on name variable on hello will affect the name variable on neither hello2 nor the environment.

Currying

You can curry a closure, but you can’t with normal C# anonymous method. No, we are not talking about some kind of tasty Thai food. Straight to the example:

ConcatDelegate concat =

delegate (string a, string b)

{

       Console.WriteLine(a + b);

};

In Ruby, one can dynamically *customise* the closure by hardwiring the first parameter as “Hello” for example. Thus calling helloConcat(“world”) will print out “Hello, world”. There is no native support on C# 2.0 to let you derive method definitions in this fashion. Wesdyer wrote on his blog how we can achieve this using Lambda Expression in C# 3.0.

In C# 2.0, LinFu provides support for this closure feature on .Net delegate. LinFu is a fairly large general-purpose AOP-centric framework by itself, and closure is only a very small part of it. This is how you can achieve currying with LinFu:

ConcatDelegate concat =

delegate (string a, string b)

{

       Console.WriteLine(a + b);

};

 

Closure hello = new Closure(

concat, “Hello, “, Args.Lambda);

 

hello.Invoke(“world”);

In the code above, we derive a new method and set the first parameter as “Hello”. Args.Lambda tells the closure to replace with actual value passed to the Invoke method when called. More on LinFu closure can be checked out here.

I will post specific blogs about LinFu in due course. I’m pretty much a new fansboy of LinFu. LinFu rocks!