What is a Closure?
Closures may be defined as a set of behaviour or instructions that are encapsulated as an object such that it could be sent to other object yet can hold the context of the caller. In other words, a closures are special object that are encapsulated into an object but can hold the context of the caller.
In C# we define closures using delegates. In C# 3.0 we have language support to easily declare a delegate in a program. This widely increases the use of delegates in the program using lamda expressions. Lets put the closures in terms of some examples.
static void Main(string[] args) { int i = 20; Action myAction = () => Console.WriteLine("value of i = {0}", i); Program.RunMe(myAction); Console.ReadLine(); } public static void RunMe(Action myaction) { if(myaction != null) myaction(); }
When you run the above code, you will find that the 20 will be printed on the screen which is run from the method RunMe. Yes, the lamda expression ensures that the instruction set which it specifies is encapsulated within a closure so that the object could be sent on any other objects. As you can see, I am using the contextual variable i from within the RunMe method, hence you can say that myAction forms a closure in C#.
If you are thinking how language implements closures, you must read my blog "Internals of Delegates" from my Internals series where I have showed you how language implementers achieved that. You can also read about Internals of LINQ for better understanding of LINQ and Lamba expressions.
Language implementers allow us to easily declare lambda expressions by giving few delegates already defined inside the framework. To name a few are Action, Action
static void Main(string[] args) { List<MyClass> lstofclass = new List<MyClass> { new MyClass { Name = "Abhishek", Credit=3000}, new MyClass { Name= "Dhananjay", Credit= 2000}, new MyClass { Name = "Kunal", Credit=6000}, new MyClass { Name= "Abhijit", Credit=9000} }; var items = lstofclass.Where(item => item.Credit > 3000); Program.ForEach<MyClass>(items, x => Console.WriteLine("Name : {0}", x.Name)); Console.ReadLine(); } public static void ForEach<T1>(IEnumerable<T1> source, Action<T1> myaction) { foreach (var x in source) myaction(x); }
Now in the above example, I have declared a list of object with two properties, Name and Credit. Now I am filtering the list using Where extension method defined in the framework. The Where is an extension method which takes a closure as argument and filters the data according to what we define inside. To understand how this is done, lets take an example of how a normal foreach loop into one that implements closures.
We pass items as argument for our Foreach and a closure which prints the name. Now from the Foreach loop, I just call the method directly using normal foreach. I hope you understand the concept. Try my sample application to understand it better.
Download Sample -26KB
Interesting thoughts
Now closures can sometimes be misleading. There are few things that you need to consider important and you must know before working with closures. As I told you that closures can access contextual values from the caller program, yet it points to the latest value rather than the value when it is created. Lets take an example to make it clear :
string x = "Hello! This is First Message"; Action myAction = () => Console.WriteLine(x); x = "The value is changed here"; myAction(); Console.ReadLine();
If you run this code, you will see the output is "The value is changed here". Hence you should remember the closures point to the latest value of the contextual variable when it is called rater than when it is created.
Even if you declare x as integer, yet it will show up the latest value.
So why this happens, actually C# compiler create a new class which holds the value X inside it. When we invoke the member, it creates an object of the (compiler generated) class and pass the latest value. Hence you would see only the latest value of context. Hence we can say Closures close over variable rather than value.
There is an interesting blog by Eric where he showed why closures over loops are harmful which you can read for further interesting reading.
Closing Note
In our current day programming, Closures really holds a special position. We have increased the usage of closures in our program yet knowing the fact what it is capable of. In this blog post, I have tried to make you engulf some of the interesting facts around closures of C#, but there is sea around you and its time for you to discover newer facts about it. Go on, use it in your program, and write to me if you find anything interesting.
Thank you for reading.
Keep in touch.
Hi, I like this blog.
ReplyDeleteSimple but good explanation of Closures in C#. Thanks.
ReplyDeleteGood one Abhishek !
ReplyDelete