Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do closures work behind the scenes? (C#)

Tags:

closures

c#

.net

I feel I have a pretty decent understanding of closures, how to use them, and when they can be useful. But what I don't understand is how they actually work behind the scenes in memory. Some example code:

public Action Counter() {     int count = 0;     Action counter = () =>     {         count++;     };      return counter; } 

Normally, if {count} was not captured by the closure, its lifecycle would be scoped to the Counter() method, and after it completes it would go away with the rest of the stack allocation for Counter(). What happens though when it is closured? Does the whole stack allocation for this call of Counter() stick around? Does it copy {count} to the heap? Does it never actually get allocated on the stack, but recognized by the compiler as being closured and therefore always lives on the heap?

For this particular question, I'm primarily interested in how this works in C#, but would not be opposed to comparisons against other languages that support closures.

like image 879
Matt Avatar asked Dec 18 '09 14:12

Matt


People also ask

What are closures in C?

A closure is a kind of object that contains a pointer or reference of some kind to a function to be executed along with the an instance of the data needed by the function.

How are closures implemented?

Closures are typically implemented with a special data structure that contains a pointer to the function code, plus a representation of the function's lexical environment (i.e., the set of available variables) at the time when the closure was created.

How are closures implemented in JavaScript?

Whenever a function is declared in JavaScript closure is created. Returning a function from inside another function is the classic example of closure, because the state inside the outer function is implicitly available to the returned inner function, even after the outer function has completed execution.

Where are closure variables stored?

So. With this in mind, the answer is that variables in a closure are stored in the stack and heap.


2 Answers

Your third guess is correct. The compiler will generate code like this:

private class Locals {   public int count;   public void Anonymous()   {     this.count++;   } }  public Action Counter() {   Locals locals = new Locals();   locals.count = 0;   Action counter = new Action(locals.Anonymous);   return counter; } 

Make sense?

Also, you asked for comparisons. VB and JScript both create closures in pretty much the same way.

like image 110
Eric Lippert Avatar answered Sep 18 '22 10:09

Eric Lippert


The compiler (as opposed to the runtime) creates another class/type. The function with your closure and any variables you closed over/hoisted/captured are re-written throughout your code as members of that class. A closure in .Net is implemented as one instance of this hidden class.

That means your count variable is a member of a different class entirely, and the lifetime of that class works like any other clr object; it's not eligible for garbage collection until it's no longer rooted. That means as long as you have a callable reference to the method it's not going anywhere.

like image 39
Joel Coehoorn Avatar answered Sep 18 '22 10:09

Joel Coehoorn