tags:

views:

2404

answers:

7

What is a 'closure'? Do we have them in .NET?


If they do exist in .NET, could you please provide a code snippet (preferably in C#) explaining it?


EDIT: I went through Jon Skeet's article to understand what closures are and how to use them in .NET.
EDIT: I found another interesting article here

+2  A: 

Closures are functional values that hold onto variable values from their original scope. C# can use them in the form of anonymous delegates.

For a very simple example, take this C# code:

    delegate int testDel();

    static void Main(string[] args)
    {
        int foo = 4;
        testDel myClosure = delegate()
        {
            return foo;
        };
        int bar = myClosure();

    }

At the end of it, bar will be set to 4, and the myClosure delegate can be passed around to be used elsewhere in the program.

Closures can be used for a lot of useful things, like delayed execution or to simplify interfaces - LINQ is mainly built using closures. The most immediate way it comes in handy for most developers is adding event handlers to dynamically created controls - you can use closures to add behavior when the control is instantiated, rather than storing data elsewhere.

Dan Monego
the statement is just storing a variable...?
jjnguy
I suspect it's being edited :)
Jon Skeet
Twitchy enter-key finger. :)
Dan Monego
+37  A: 

I have an article on this very topic. (It has lots of examples.)

In essence, a closure is a block of code which can be executed at a later time, but which maintains the environment in which it was first created - i.e. it can still use the local variables etc of the method which created it, even after that method has finished executing.

The general feature of closures is implemented in C# by anonymous methods and lambda expressions.

Here's an example using an anonymous method:

using System;

class Test
{
    static void Main()
    {
        Action action = CreateAction();
        action();
        action();
    }

    static Action CreateAction()
    {
        int counter = 0;
        return delegate
        {
            // Yes, it could be done in one statement; 
            // but it is clearer like this.
            counter++;
            Console.WriteLine("counter={0}", counter);
        };
    }
}

Here we can see that the action returned by CreateAction still has access to the counter variable, and can indeed increment it, even though CreateAction itself has finished.

Jon Skeet
Might be nice to add a code snippet, as requested...
Jason Bunting
Yeah, I was just thinking that (although the article has *lots* of them in.)
Jon Skeet
Yeah, but it helps to include one here, so that in case your link ever gets stale (heaven forbid), your post here still has some info.
Jason Bunting
Thanks Jon. BTW, is there something that you don't know in .NET? :) Who do you go to when you have questions?
Nick
There's always more to learn :) I've just finished reading CLR via C# - very informative. Other than that, I usually ask Marc Gravell for WCF/binding/expression trees, and Eric Lippert for C# language things.
Jon Skeet
To say a closure is "a block of code" isn't technically correct; it has to do with scope hanging around after it was originally defined. A "block of code" is a means to obtaining a closure, but not technically a closure.
Jason Bunting
I've got the scope part later in the sentence. You could arguably use the word "function" instead of "block of code" but I think the scope part is covered.
Jon Skeet
I noticed that, but I still think your statement about it being "a block of code which can be executed at a later time" is simply incorrect - it has nothing to do with execution, more to do with variable values and the scope than execution, per se.
Jason Bunting
I'd say that closures aren't useful unless they can be executed, and the "at a later time" highlights the "oddness" of being able to capture the environment (which might otherwise have gone away by execution time). If you only quote *half* the sentence then it's an incomplete answer, of course.
Jon Skeet
A: 

A closure is a function, defined within a function, that can access the local variables of it as well as its parent.

public string GetByName(string name)
{
   List<things> theThings = new List<things>();
  return  theThings.Find<things>(t => t.Name == name)[0];
}

so the function inside the find method.

 t => t.Name == name

can access the variables inside its scope, t, and the variable name which is in its parents scope. Even though it is executed by the find method as a delegate, from another scope all together.

DevelopingChris
A closure isn't a function, per se, it is more defined by talking about scope than functions. Functions merely assist in keeping the scope around, which causes a closure to be created. But to say a closure is a function isn't technically correct. Sorry to nitpick. :)
Jason Bunting
A: 
Func<int, int> GetMultiplier(int a)
{
     return delegate(int b) { return a * b; }
}
//...
var fn2 = GetMultiplier(2);
var fn3 = GetMultiplier(3);
Console.WriteLine(fn2(2));  //outputs 4
Console.WriteLine(fn2(3));  //outputs 6
Console.WriteLine(fn3(2));  //outputs 6
Console.WriteLine(fn3(3));  //outputs 9

A closure is an anonymous function passed outside of the function in which it is created. It maintains any variables from the function in which it is created that it uses.

AnthonyWJones
That isn't currying, that is partial application. You might want to read up on the difference, it is subtle enough that many people get it wrong as you have here.
Jason Bunting
You're quite right, edited.
AnthonyWJones
A: 

Closures are chunks of code that reference a variable outside themselves, (from below them on the stack), that might be called or executed later, (like when an event or delegate is defined, and could get called at some indefinite future point in time)... Because the outside variable that the chunk of code references may gone out of scope (and would otherwise have been lost), the fact that it is referenced by the chunk of code (called a closure) tells the runtime to "hold" that variable in scope until it is no longer needed by the closure chunk of code...

Charles Bretana
As I indicated on someone else's explanation: I hate to be technical, but closure has more to do with scope - a closure can be created in a couple of different ways, but a closure isn't the means, it is the end.
Jason Bunting
Closures are relatively new to me, so it's entirely possible I misunderstand, but I get the scope part.. My answer is focused around scope. So I am missing what yr comment is trying to correct... What else can scope be relevant to but some chunk of code? (function, anonymous method, or whatever)
Charles Bretana
Isn't the key to a closure that some "chunk of runnable code" can access a variable or in-memory value that it syntactically "outside" of it's scope, after that variable should have ordinarily gone "out of scope" or been destroyed?
Charles Bretana
And @Jason, no worries about being technical, this closure idea is something I took a while to get my head wrapped around, in long discussions with a co-worker, about javascript closures... but he was a Lisp nut and I never quite got through the abstractions in his explanations...
Charles Bretana
+3  A: 

Here is a contrived example for C# which I created from similar code in JavaScript:

public delegate T Iterator<T>() where T : class;

public Iterator<T> CreateIterator<T>(IList<T> x) where T : class
{
        var i = 0; 
        return delegate { return (i < x.Count) ? x[i++] : null; };
}

So, here is some code that shows how to use the above code...

var iterator = CreateIterator(new string[3] { "Foo", "Bar", "Baz"});

// So, although CreateIterator() has been called and returned, the variable 
// "i" within CreateIterator() will live on because of a closure created 
// within that method, so that every time the anonymous delegate returned 
// from it is called (by calling iterator()) it's value will increment.

string currentString;    
currentString = iterator(); // currentString is now "Foo"
currentString = iterator(); // currentString is now "Bar"
currentString = iterator(); // currentString is now "Baz"
currentString = iterator(); // currentString is now null

Hope that is somewhat helpful.

Jason Bunting
Sure thing - not as clear as it could be, but clearer than it might be. :P
Jason Bunting
You've given an example, but didn't offer a general definition. I gather from your comments here that they are 'more about scope', but surely there's more to it than that?
ladenedge
+1  A: 

Basically closure is a block of code that you can pass as an argument to a function. C# supports closures in form of anonymous delegates.

Here is a simple example:
List.Find method can accept and execute piece of code (closure) to find list's item.

// Passing a block of code as a function argument
List<int> ints = new List<int> {1, 2, 3};
ints.Find(delegate(int value) { return value == 1; });

Using C#3.0 syntax we can write this as:

ints.Find(value => value == 1);
aku
I hate to be technical, but closure has more to do with scope - a closure can be created in a couple of different ways, but a closure isn't the means, it is the end.
Jason Bunting