Skip to main content

Closures in C# vs JavaScript -
Same But Different

Closure in a Nutshell

Closures are a Software phenomenon which exist in several languages, in which methods declared inside other methods (nested methods), capture variables declared inside the outer methods. This behavior makes captured variables available even after the outer method's scope has vanished.

The following pseudo-code demonstrates the simplest sample:
    Main() //* Program starts from here
    {
        Closures();
    }

    AgeCalculator()
    {
        int myAge = 30;
        return() => {
            //* Returns the correct answer although AgeCalculator method Scope should have ordinarily disappear
            return myAge++;
        };
    }

    Closures()
    {
        Func ageCalculator = AgeCalculator();
            //* At this point AgeCalculator scopeid cleared, but the captured values keeps to live
            Log(ageCalculator()); //* Result: 30
            Log(ageCalculator()); //* Result: 31
    }
JavaScript and C# are two languages that support Closures. In this Post I will explain the different internal implementations of this phenomenon in these two languages.

NOTE: Although tested only in C#, I believe the same behavior is valid for all CLR compliant languages.

C# Closures

Simple C# Closures

I fixed the previous pseudo-code to a Compilable C# representation:
    Func<int> AgeCalculator()
    {
        int myAge = 30;
        return() => myAge++;
    }

    void Closure()
    {
        Func<int> ageCalculator = AgeCalculator();
        Console.WriteLine(ageCalculator());
        Console.WriteLine(ageCalculator());
    }
Internally, Closures are implemented in C# by encapsulating the captured variables into fields of a new generated (at compile time) class. This class pointer is used instead of the 'simple' myAge variable:

NOTE: The following is a generated code, I just beautify it a bit to make it more readable
    private Func<int> AgeCalculator()
    {
        // * New generated class that encapsulates myAge variable as a field and AgeCalculator as a regular method that just increases myAge variable
        __Plain__.__DisplayClass1 cDisplayClass1 = new __Plain__.__DisplayClass1();
        cDisplayClass1.myAge = 30;
        return new Func<int>((object) cDisplayClass1, __methodptr(AgeCalculator));
    }

    [CompilerGenerated]
    private sealed class__DisplayClass1
    {
        public int myAge; // * As a field

        public __DisplayClass1()
        {
            base.ctor();
        }

        public int AgeCalculator() //* Simple method
        {
            return this.myAge++;
        }
     }
We can see that a new cDispalyClass1 object was created and within it the myAge variable and a new AgeCalculator method. This object's pointer continues to live even after privateFunc AgeCalculator() scope is cleared, just because it is treated like a normal pointer.

Because of this .NET compiler implementation, captured types are evaluated always at runtime and NOT at capture time, because all closures point to the same object and its variable. Even if fields are altered, the change affects all of them:
    private void ClosureSample5()
    {
        Action[] printerList = newAction[3];
        string i = "A";
        printerList[0] = () => Console.Write(i);
        i = "B";
        printerList[1] = () => Console.Write(i);
        i = "C";
        printerList[2] = () => Console.Write(i);
        i = "D";
        foreach (Action printer in printerList)
            printer(); //* Result: DDD instead of ABC
    }
As explained above, the compiler generates a class containing the 'i' variable and 3 separate 'Closure5' methods. The class is instantiated and the object is used by all closures:

NOTE: Generated & beautified
    private void Closure5()
    {
        __Plain__.__DisplayClass3 cDisplayClass3 = new __Plain__.__DisplayClass3();
        Action[] actionArray = new Action[3];
        cDisplayClass3.i = "A";

        actionArray[0] = new Action((object) cDisplayClass3, __methodptr(Closure5_0));
        cDisplayClass3.i = "B";

        actionArray[1] = new Action((object) cDisplayClass3, __methodptr(Closure5_1));
        cDisplayClass3.i = "C";

        actionArray[2] = new Action((object) cDisplayClass3, __methodptr(Closure5_2));
        cDisplayClass3.i = "D";
        foreach (Action action in actionArray)
            action();
    }

    private sealed class __DisplayClass3
    {
        publicstring i;

        public__DisplayClass3()
        {
            base.\u002Ector();
        }

        public void Closure5__0()
        {
            Console.Write(this.i);
        }

        public void Closure5__1()
        {
            Console.Write(this.i);
        }

        public void Closure5__2()
        {
            Console.Write(this.i);
        }
    }
This implementation is self explanatory. Also, in this example a new cDisplayClass3 object has been auto generated and used like a normal pointer.

In Loops

Another place where Closure can effect your code is nested methods declared inside loops. Let's see an example:
    private void Closure2()
    {
        Action[] actions = newAction[5];
        for (int i = 0; i < 5; i++)
        {
            actions[i] = () => Console.Write(i);
        }

        foreach (Action action in actions)
            action(); //* Result 55555
    }
We could have thought that the result would be 01234, but actually the final result is 55555 because the compiler "hoists" the iterator variable 'i' outside the 'for' loop inside cDisplayClass1, like all other closure samples above.
By "hoisting" the variable outside of the loop, the cDisplayClass1 is shared by all lambda expressions. When 'i' value is changed, it's changed for all of them.

If the the compiler would have initialized cDisplayClass1 inside a 'for' loop, each Action would have got it's private instance.

NOTE: Generated & beautified
    private void Closure2()
    {
        Action[] actionArray = newAction[5];
        __Plain__.__DisplayClass1 cDisplayClass1 = new__Plain__.__DisplayClass1();
        for(cDisplayClass1.i = 0; cDisplayClass1.i < 5; ++cDisplayClass1.i)
        {
            actionArray[cDisplayClass1.i] = new Action((object) cDisplayClass1, __methodptr(Closure2__0));
        }
        foreach(Action action in actionArray)
            action();
    }
This strange behavior inside loops is well documented throughout the Web, and the standard suggested fix is to declare another variable inside the curly brackets, filling it with the value of the iteration variable 'i'.
    private void Closure2()
    {
        Action[] actions = newAction[5];
        for (int i = 0; i < 5; i++)
        {
            int internalInt = i;
            actions[internalInt] = () => Console.Write(internalInt);
        }

        foreach (Action action in actions)
            action(); //* Result: 01234
    }
The reason why this fixes the behavior is that when the compiler encounters this code, it initializes the cDisplayClass1 object inside the curly brackets. By doing so every Action gets it's own instance.

NOTE: Generated & beautified
    private void Closure2()
    {
        Action[] actionArray = newAction[5];
        for(int index = 0; index < 5; ++index)
        {
            __Plain__.__DisplayClass1 cDisplayClass1 = new__Plain__.__DisplayClass1();
            cDisplayClass1.internalInt = index;

            actionArray[cDisplayClass1.internalInt] = newAction((object) cDisplayClass1, __methodptr(\Closure2__0));
        }
        foreach(Action actioninactionArray)
            action();
    }

JavaScript Closures

Simple JS Closures

The first thing I would like to highlight is that in JS, closures are not just a phenomenon, but actually a strong feature of the language (Just be careful how you use closures in JS or you may come across memory issues).
The internal implementation of a closure in JS is totally different then C#. I won't explain JS closure top to bottom in this article, the web is full of documentation about this subject, like Dmitry Soshnikov's great article about ECMAScript Closures.

To put it shortly; any time we access a method in JS, a special context object is created. This object contains the variables to be searched in the scope chain search process.
    var x = 10;
    (function parentFunc () {
        console.log(x);
    }()); //* Result: 10
The code above will print 10, because when parentFunc method is executed, a special context object containing it's parent's variables is created and is pointed by parentFunc method scope.
When the interpreter starts searching for 'x' value it searches inside parentFunc scope. If it can not find it, it's parent scope gets evaluated. In this case the parent scope is the global scope (window in browsers implementation, global in nodeJS).

Closures in JS are implemented the same way. This is not an interpreter trick, but a language feature. Inner functions actually capture the entire parent scope and add it to the chain:
    var x = 10;
    var funcResult = (function parentFunc () {
        var x = 20;
        var y =30;
        var sonFunc = function () {
            console.log(x + y);
        }
        return sonFunc;
    })();
    funcResult();//* Result 50
When sonFunc is returned, the parentFunc scope with x (20) and y (30) variables is captured and added to the search chain.
When funcResult is called, and console.log(x + y) is encountered, the interpreter searches the variables 'x' and 'y' inside sonFunc. Once it concludes it can't find them, it searches them inside it's parent scope, (as I've explained, parentFunc was added to the chain).

Note that if we comment-out var x = 20 code line, the result will be 40. Because the interpreter won't find the 'x' variable inside parentFunc, it will search in parentFunc's parent scope where 'x' value is 10.

In Loops

The same is true when talking about loops in JS. As in C#, when an iterator variable is used within the inner method, it's value will be the value at runtime and not the value at capture time:
    var myResultFuncList = function () {
        var resultFuncList = [];
        for (var i = 0; i < 5; i++) {
            resultFuncList[i] = function () {
                console.log(i);
            }
        }
        return resultFuncList;
    };
    var list = myResultFuncList();

    for (func in list) {
        list[func](); //* Result: 55555
    }
The result of this method is not 01234 as expected, but 55555 instead. Because all the created functions inside resutFuncList have added their shared parent context in the search chain, when the 'i' value changes, it affects the entire function, as all of them just point to the same parent context object in which 'i' resides

...But Different

There are two big difference in JS, that prevents us using the same trick we used in C# in order to change this behavior:
  1. In JS, the closure implementation is different than in C#, will be explained later.
  2. In C# every code inside curly brackets gets it's own scope, meaning that variables declared inside curly brackets can be accessed only within the curly brackets.
    In JS curly brackets doesn't create a new scope, the variables are shared for the entire function.
    So even if we declare a variable inside the 'for' loop JS interpreter will "hoist" the variable to the beginning of the function and it will be treated like any other "function variable". [Adjusted Thanks to Adar's Comment]

    
var myResultFuncList = function () {
         //* 'Hoisted' here:  var niceTry; (undefined)
        var resultFuncList = [];
        for (var i = 0; i < 5; i++) {
            var niceTry = i;  //* Hoisted to the top of the function
            resultFuncList[i] = (function () {
                console.log(niceTry);
            });
         }
         return resultFuncList;
    }

    var list = myResultFuncList();

    for (func in list) {
        list[func]();  //* Result: 55555
    }
In JS, the closure implementation is different than in C#. The result remains 55555 even when a new variable is used to hold the 'i' value.
In the example above, niceTry variable is treated exactly like the 'i' variable. Its just another variable captured inside the parent context object.
The way to change this behavior in JS, is by creating new scopes for every single returned method:
    var myResultFuncList = function () {
        var resultFuncList = [];
        for (var i = 0; i < 5; i++) {
            resultFuncList[i] = (function (iterator) {
                return function () {
                    console.log(iterator);
                }
            })(i);
        }
        return resultFuncList;
    }

    var list = myResultFuncList();

    for (func in list) {
        list[func]();
    }
Now the result is 01234. Because every returned function was wrapped by a parent function, these functions become the parents scope in the chain search process, and each of them capture a different value of the iterator variable.

Just remember, if you see nested methods make sure you handle Closures correctly.

Comments

Adar Wesley said…
Very nice article!

Just one small comment. The reason why local variables are treated differently in JS closures is not because of the closure implementation, but rather because of variable definitoon rules. In JS, all variable definitions are "hoisted" up to the finction level. This means that defining the variable inside the loop has no meaning. It's exactly the same as declaring it at the top of the function.
The only way to create an inner scope is to wrap the relevant code in another function.

---
Adar Wesley
Gabi Beyo said…
Hi Adar. Thank you for your comment.
The reason is a combination of the two:
1 - The way closure is implemented, via the scope chain
2 - Like you mentioned, variables "hoisting"

I will adjust the Post and add the second point as well.
Hi Gabi

Thx

Your closure explanation Helped me to solve issue with creating multiply timers in a loop

Nachum
Very very nice article.
Thank you for sharing.

The Best

GetHashCode Hands-On Session

The following is a hands-on post meant to demonstrate how GetHashCode() and Equals() methods are used by .NET Framework under the hood. For the sake of simplicity I will refer to the popular hashed-base Dictionary type, although any other hash based structure will follow a similar behavior, if not the same one. After understanding this post you should be able to spot potential problematic behaviors and resolve them, prevent creation of unreachable items in dictionaries and improve CRUD actions performance on hash based structures. The TheoryGetHashCode() is used to create a unique integer identifier for objects/structs. The hashcode can be used for two purposes: Programmatically, by developers, to distinguish objects/structs form each other (NOTE: Not recommended when the default .NET implementation is used, as it's not guaranteed to preserve the same hash between .NET versions and platforms)Internally, by .NET Framework, when using the object/struct as a key in a hashed based l…

Method Breakpoints are Evil

Some IDEs expose an option to set "Method Breakpoints", it turns out that "Method Breakpoints" might tremendously decrease debugger's performance. In this article, I explain what are "Method Breakpoints" and the reasons they impact performance so badly. To better understand this subject I will cover how Debuggers works under the hoods and how Breakpoints and Method Breakpoints are implemented internally. Java Platform Debugger Architecture JDPA is an architecture designed for enabling communication between debuggers and debugees. The architecture consists of three APIs: JVM Tool Interface (JVM TI) - A native interface which defines the services a VM must provide for debugging purposes Java Debug Wire Protocol (JWDP) - A textual API which defines the communication's protocol between debugee and debuggerJava Debug Interface (JDI) - Defines a high-level Java API designed to facilitate the interaction between debugge and debuggers. Internally J…