Closure in Javascript vs C#

Java vs C#

As Jon Skeet pointed out in this excellent article on closures, the strategies of capturing the execution context which the behaviour is bound to different between Java and C#. C# captures the variable itself, whereas Java captures the value of the variable. To illustrate the difference, here’s Jon’s original example in C#:

// First build a list of actions
List<Action> actions = new List<Action>();

for (int counter = 0; counter < 10; counter++)
{
    actions.Add(() => Console.WriteLine(counter));
}

// Then execute them
foreach (Action action in actions)
{
    action();
}

This code actually writes 10 ten times instead of 0 to 9 because the context the actions are bound to is the variable counter, and at the time of execution the value of counter is 10 hence why each Action delegate writes 10 instead of the value of counter at the time the Action delegate was created.

The equivalent code in Java would print 0 to 9 because Java’s closure implementation captures the value of the variable instead.

However, as Jon pointed out, whilst Java’s implementation is more intuitive and easier to understand (less WTF bugs), C#’s implementation is more flexible as you can just easily mimic the effect of capturing the variable’s value by using a local variable:

// First build a list of actions
List<Action> actions = new List<Action>();

for (int counter = 0; counter < 10; counter++)
{
    int copy = counter;
    actions.Add(() => Console.WriteLine(copy));
}

// Then execute them
foreach (Action action in actions)
{
    action();
}

Javascipt vs C# (Updated 16/01/2011)

Thanks for Jens for pointing out my initial incorrect assessment (see comment), so I revised my test and used a more straight forward test using just one private variable:

function test () {
    var i = 10;
    
    // create the closure
    var func = function () { return i; };

    // 10
    alert(func());

    i = 11;
    // 11? or 10?
    alert(func());
}

The test here is simple, we create a function func which returns the value of the private variable i, whose value is then changed later on. If Javascript captures the value of the variable then the second time func is invoke the alert message would still be 10, otherwise it’ll be 11 which is the current value of i.

And the answer is?

.

.

.

Javascript captures the reference of the variable, and the second alert message is 11.

References:

Jon Skeet’s article on closures

Article on Javascript closures

  • Jens

    (f in functions) iterates the integer indices of the array: 0 through 9. It does not invoke any functions. You intended this:

    output += functions[f]() + “\n”;

    That will output 10, 10 times.

    Furthermore, by not declaring i, you’ve made it a global. Since it’s a global variable, it isn’t part of the closure anyway.

    JavaScript closure is by reference, not by value. If you wanted to capture the value of i on each iteration, you could use another level of indirection:

    functions[i] = function(j) { return function () { return j; } }(i);

  • Daniel NN

    Hey Yan,

    I don’t know very much about JavaScript, but I do know about Java. Surely the key thing here is the use of primitives? If you’re using a primitive int rather than an object reference, then in Java you’re always going to pass the value in as a parameter instead of the reference. If you use a reference (e.g. a boxed Integer or any other object) then the behaviour will be more like your C# example.

    I may be wrong on this, but I think that C# doesn’t have pure primitives in the way Java does? If C# treats every variable as an object, then you’d always expect it to pass in the object reference into the closure?

    Hope all’s well
    Daniel

  • theburningmonk

    Hey Daniel,

    C# does have pure primitives and primitive types falls onto the stack along with all other value types, in terms of difference from Java, there are no wrapper reference types for the primitive types. I.e double and Double in C# is exactly the same Double is just an alias for double, whereas Double in Java is the reference type equivalent of the primitive type double.

    Also, you can create your own value types in C# using the struct keyword which you can’t in Java (correct me here if I’m wrong, this was the case when we learnt Java in uni). Internally how the CLR implements closure and how it deals with value types (which gets popped off the stack when once it’s outside of its scope) is beyond me but it works!

    I haven’t tried out the same example in Java myself, I can try it out and confirm but Jon Skeet is almost never wrong with these kinds of things lol