Tuesday, October 13, 2009

Functional .Net : Closures

One of the more commonly used functional techniques that can be used in C# is the use of Closures, a technique that if your are currently using lambdas, you may be using them inadvertently. My understanding of closure may be different to others as there seems to be so many subtlety different definitions especially when comparing languages. Anyway, in my mind the comments of Javascript closure best align with my understanding (http://www.jibbering.com/faq/faq_notes/closures.html)

A closure is a delegate that has references to a variable not passed to it and in an scope outside the delegates immediate scope.

Like any delegate its definition and execution are not the same thing. You can define a closure and never use it or just call it later

A simple closure example I can think of is:

static void Main(string[] args)
{
var timesToRepeat = 100;
//Declare the Action
Action<string> print = text => //text (string) is the only parameter
{
//using varb declared outside of Action
for (int i = 0; i < timesToRepeat; i++)
{
Console.WriteLine(text);
}
};
timesToRepeat = 3;//Lets modify the variable
print("Hello!");//Call the action/evaluate the expression
//Prints:
//Hello!
//Hello!
//Hello!
}


Note that the timeToRepeat variable is declared outside of the declaration of the lambda statement. Think about this; the Action 'print' can be passed out side of this scope, it could be passed to another class which does not have visibility of the locally declared variable. The 'print' expression is bound to that variable declared outside of its scope. This obviously has ramification in terms of holding reference to that object. Please also note that the expression 'print', like all delegates is evaluated when it is called, not when it is declared; Stepping over the above code will not print when declaring the 'print' Action but at the last line when it is called. One last thing to note is that the variable timetoRepeat is modified after defining the print Action and this is carried when we call 'print' in the last line; "Hello!" is printed 3 times, not 100 times as the variable would imply when the closure was declared.



You may have been using closures with out knowing it. Javascript and the associated libraries like jQuery use this technique a lot, as do many open source library such as TopShelf, MassTransit etc.

No comments: