tags:

views:

335

answers:

3

I still don't quite understand what a closure is so I posted these two examples and I want to know whether these examples are both closures or not?

Example A:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

Action<string> FilterSubFoldersStartA =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith("A")));

FilterSubFoldersStartA(@"c:\tempa");
FilterSubFoldersStartA(@"c:\tempb");

Example B:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

string filter = "A";

Action<string> FilterSubFoldersStartGen =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith(filter)));

FilterSubFoldersStartGen(@"c:\tempa");

filter = "B"; 

FilterSubFoldersStartGen(@"c:\tempb");
+4  A: 

Yea, a closure is nothing more than a function that "saves" some variables from the environment in which it is defined. So in both of your examples, the defined action saves the list named subFolders, which can be referenced by the functions even after the local variable is out of scope. The filter variable in the second example is also saved by the defined function.

A more precise definition here

Mario
+7  A: 

Your second example makes use of closures (technically you could say that the compiler computes a closure in both cases, but you don't make use of it in the first case).

A closure is simply "all the variables visible to this function". Nothing more, nothing less. And obviously, in both cases, those variables exist, and are determined by the compiler.

But what we usually mean when we talk about "using closures" is that lambda expressions can use all local variables visible at the place they're declared. They're all part of its closure.

In your case, d is simply the parameter to the lambda function, and since that's all you use in the first case, you're not really taking advantage of closures.

In the second case, filter is not defined in the lambda expression, it's not a parameter or anything. It's a local variable which just so happens to be visible at the place where the lambda is declared. So it is part of the lambda's closure, which allows you to reference it in the body of the lambda.

Edit
As pointed out in the comments, I didn't read your code too closely. I only noticed the second lambda expression in each example. The first lambda does use closures (it closes over subFolders in both cases.)

jalf
The first example closes over `subFolders` so it’s also a closure.
Konrad Rudolph
Oh right, I didn't even notice the first lambda. I just saw the `d =>...` one. You're right. The first one closes over `subFolders`, and in the second case, the second lambda closes over `filter`.
jalf
A: 

Both examples have closures. In "A" anonymous method captures local variable subFolders. In "B" anonymous method captures local variables subFolders and filter. Also take a look here.

P.S. Also note that you are actually using closure in "A" because you are using subFolders variable.

AlexD