In the preparation for a C# exam at university I found the following multiple choice question:
Client applications call your library by passing a set of operations
to perform. Your library must ensure that system resources are most
effectively used. Jobs may be scheduled in any order, but your
librarymust log the position of each operation. You have declared this
code:
public IEnumerable<Task> Execute(Action[] jobs)
{
var tasks = new Task[jobs.Length];
for (var i = 0; i < jobs.Length; i++)
{
/* COMPLETION NEEDED */
}
return tasks;
}
public void RunJob(Action job, int index)
{
// implementation omitted
}
Complete the method by inserting code in the for loop. Choose the
correct answer.
1.)
tasks[i] = new Task((idx) => RunJob(jobs[(int)idx], (int)idx), i);
tasks[i].Start();
2.)
tasks[i] = new Task(() => RunJob(jobs[i], i));
tasks[i].Start();
3.)
tasks[i] = Task.Run(() => RunJob(jobs[i], i));
I have opted for answer 3 since Task.Run() queues the specified work on the thread pool and returns a Task object that represents the work.
But the correct answer was 1, using the Task(Action, Object) constructor. The explanation says the following:
In answer 1, the second argument to the constructor is passed as the
only argument to the Action delegate. The current value of the
i variable is captured when the value is boxed and passed to the Task
constructor.
Answer 2 and 3 use a lambda expression that captures the i variable
from the enclosing method. The lambda expression will probably return
the final value of i, in this case 10, before the operating system
preempts the current thread and begins every task delegate created by
the loop. The exact value cannot be determined because the OS
schedules thread execution based on many factors external to your
program.
While I perfectly understand the explanation of answer 1, I don't get the point in the explanations for answer 2 and 3. Why would the lambda expression return the final value?
In options 2 and 3 lambda captures original i variable used in for loop. It's not guaranteed when tasks will be run on thread pool. So possible behavior: for loop is finished, i=10 and then tasks are started to execute. So all of them will use i=10.
Similar behavior you can see here:
void Do()
{
var actions = new List<Action>();
for (int i = 0; i < 3; i++)
{
actions.Add(() => Console.WriteLine(i));
}
//actions executed after loop is finished
foreach(var a in actions)
{
a();
}
}
Output is:
3
3
3
You can fix it like this:
for (int i = 0; i < 3; i++)
{
var local = i;
actions.Add(() => Console.WriteLine(local));
}
This question already has answers here:
Using the iterator variable of foreach loop in a lambda expression - why fails?
(3 answers)
Closed 8 years ago.
I got this piece of code,
delegate void Printer();
static void Main(string[] args)
{
List<Printer> printers = new List<Printer>();
for (int i = 0; i < 10; i++)
{
printers.Add(delegate { Console.WriteLine(i); });
}
foreach (Printer printer in printers)
{
printer();
}
Console.ReadLine();
}
Here the output is '10' for ten times.
The scope of i is with in the for loop. But while we retrieve in out side that we are still getting value from i.
How is it possible?
You have modified closure. Try this:
for (int i = 0; i < 10; i++)
{
int ii = i;
printers.Add(delegate { Console.WriteLine(ii); });
}
When you use in your anonymous method access the the variable in you local scope it creates closure.
The code in the delegate is not run until it is called, which happens in the second loop. It then refers to the i which was defined within the scope of the first loop, but with it's current value - and since the first loop has been completed already, i will be 10 each time.
I believe each of the delegates you create are given the same scope as the first loop, if that makes sense. This means that each i has it's delegate as it's scope, and since each delegate is defined within the scope of the first loop, each i will also have the loop as it's scope, even if the delegate logic is called outside that scope, as in your example.
Since i is valid throughout / across several iterations of the loop, it gets updated, and is always 10 by the time the delegates get called.
This explains why the following works as a fix:
for(int i = 0; i < 10; i++)
{
var localVar = i; // Only valid within a single iteration of the loop!
printers.Add(delegate { Console.WriteLine(localVar); });
}
Let's unroll the loop:
int i=0;
printers.Add(delegate { Console.WriteLine(i); })
i=1;
printers.Add(delegate { Console.WriteLine(i); })
...
i=10;
printers.Add(delegate { Console.WriteLine(i); })
As you can see the i variable is captured within the delegate, and the delegate itself is not run until the loop ends, and the variable has achieved the last value (10).
A simple workaround is to assign the loop variable to a local helper variable
for (int i = 0; i < 10; i++)
{
var index = i;
printers.Add(delegate { Console.WriteLine(index); });
}
As for the scope issue, any captured variables have their scope (and lifetime) extended. A variable used within a lambda/delegate will not be garbage collected until the delegate itself goes out of scope - which can be a problem for large objects. Specifically, section, 7.15.5.1 of the C# 5 Specification states:
When an outer variable is referenced by an anonymous function, the
outer variable is said to have been captured by the anonymous
function. Ordinarily, the lifetime of a local variable is limited to
execution of the block or statement with which it is associated
(§5.1.7). However, the lifetime of a captured outer variable is
extended at least until the delegate or expression tree created from
the anonymous function becomes eligible for garbage collection.
Each delegate is only invoked in the foreach, after the for loop. By this time, the variable i captured by the closure is already at its final value, viz 10. You can solve like so:
for (int i = 0; i < 10; i++)
{
var cache = i;
printers.Add(delegate { Console.WriteLine(cache); });
}
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?
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);
};
}
}
Output:
counter=1
counter=2
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.
If you are interested in seeing how C# implements Closure read "I know the answer (its 42) blog"
The compiler generates a class in the background to encapsulate the anoymous method and the variable j
[CompilerGenerated]
private sealed class <>c__DisplayClass2
{
public <>c__DisplayClass2();
public void <fillFunc>b__0()
{
Console.Write("{0} ", this.j);
}
public int j;
}
for the function:
static void fillFunc(int count) {
for (int i = 0; i < count; i++)
{
int j = i;
funcArr[i] = delegate()
{
Console.Write("{0} ", j);
};
}
}
Turning it into:
private static void fillFunc(int count)
{
for (int i = 0; i < count; i++)
{
Program.<>c__DisplayClass1 class1 = new Program.<>c__DisplayClass1();
class1.j = i;
Program.funcArr[i] = new Func(class1.<fillFunc>b__0);
}
}
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.
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.
A closure is when a function is defined inside another function (or method) and it uses the variables from the parent method. This use of variables which are located in a method and wrapped in a function defined within it, is called a closure.
Mark Seemann has some interesting examples of closures in his blog post where he does a parallel between oop and functional programming.
And to make it more detailed
var workingDirectory = new DirectoryInfo(Environment.CurrentDirectory);//when this variable
Func<int, string> read = id =>
{
var path = Path.Combine(workingDirectory.FullName, id + ".txt");//is used inside this function
return File.ReadAllText(path);
};//the entire process is called a closure.
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.
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...
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);
If you write an inline anonymous method (C#2) or (preferably) a Lambda expression (C#3+), an actual method is still being created. If that code is using an outer-scope local variable - you still need to pass that variable to the method somehow.
e.g. take this Linq Where clause (which is a simple extension method which passes a lambda expression):
var i = 0;
var items = new List<string>
{
"Hello","World"
};
var filtered = items.Where(x =>
// this is a predicate, i.e. a Func<T, bool> written as a lambda expression
// which is still a method actually being created for you in compile time
{
i++;
return true;
});
if you want to use i in that lambda expression, you have to pass it to that created method.
So the first question that arises is: should it be passed by value or reference?
Pass by reference is (I guess) more preferable as you get read/write access to that variable (and this is what C# does; I guess the team in Microsoft weighed the pros and cons and went with by-reference; According to Jon Skeet's article, Java went with by-value).
But then another question arises: Where to allocate that i?
Should it actually/naturally be allocated on the stack?
Well, if you allocate it on the stack and pass it by reference, there can be situations where it outlives it's own stack frame. Take this example:
static void Main(string[] args)
{
Outlive();
var list = whereItems.ToList();
Console.ReadLine();
}
static IEnumerable<string> whereItems;
static void Outlive()
{
var i = 0;
var items = new List<string>
{
"Hello","World"
};
whereItems = items.Where(x =>
{
i++;
Console.WriteLine(i);
return true;
});
}
The lambda expression (in the Where clause) again creates a method which refers to an i. If i is allocated on the stack of Outlive, then by the time you enumerate the whereItems, the i used in the generated method will point to the i of Outlive, i.e. to a place in the stack that is no longer accessible.
Ok, so we need it on the heap then.
So what the C# compiler does to support this inline anonymous/lambda, is use what is called "Closures": It creates a class on the Heap called (rather poorly) DisplayClass which has a field containing the i, and the Function that actually uses it.
Something that would be equivalent to this (you can see the IL generated using ILSpy or ILDASM):
class <>c_DisplayClass1
{
public int i;
public bool <GetFunc>b__0()
{
this.i++;
Console.WriteLine(i);
return true;
}
}
It instantiates that class in your local scope, and replaces any code relating to i or the lambda expression with that closure instance. So - anytime you are using the i in your "local scope" code where i was defined, you are actually using that DisplayClass instance field.
So if I would change the "local" i in the main method, it will actually change _DisplayClass.i ;
i.e.
var i = 0;
var items = new List<string>
{
"Hello","World"
};
var filtered = items.Where(x =>
{
i++;
return true;
});
filtered.ToList(); // will enumerate filtered, i = 2
i = 10; // i will be overwriten with 10
filtered.ToList(); // will enumerate filtered again, i = 12
Console.WriteLine(i); // should print out 12
it will print out 12, as "i = 10" goes to that dispalyclass field and changes it just before the 2nd enumeration.
A good source on the topic is this Bart De Smet Pluralsight module (requires registration) (also ignore his erroneous use of the term "Hoisting" - what (I think) he means is that the local variable (i.e. i) is changed to refer to the the new DisplayClass field).
In other news, there seems to be some misconception that "Closures" are related to loops - as I understand "Closures" are NOT a concept related to loops, but rather to anonymous methods / lambda expressions use of local scoped variables - although some trick questions use loops to demonstrate it.
A closure aims to simplify functional thinking, and it allows the runtime to manage
state, releasing extra complexity for the developer. A closure is a first-class function
with free variables that are bound in the lexical environment. Behind these buzzwords
hides a simple concept: closures are a more convenient way to give functions access
to local state and to pass data into background operations. They are special functions
that carry an implicit binding to all the nonlocal variables (also called free variables or
up-values) referenced. Moreover, a closure allows a function to access one or more nonlocal variables even when invoked outside its immediate lexical scope, and the body
of this special function can transport these free variables as a single entity, defined in
its enclosing scope. More importantly, a closure encapsulates behavior and passes it
around like any other object, granting access to the context in which the closure was
created, reading, and updating these values.
Just out of the blue,a simple and more understanding answer from the book C# 7.0 nutshell.
Pre-requisit you should know :A lambda expression can reference the local variables and parameters of the method
in which it’s defined (outer variables).
static void Main()
{
int factor = 2;
//Here factor is the variable that takes part in lambda expression.
Func<int, int> multiplier = n => n * factor;
Console.WriteLine (multiplier (3)); // 6
}
Real part:Outer variables referenced by a lambda expression are called captured variables. A lambda expression that captures variables is called a closure.
Last Point to be noted:Captured variables are evaluated when the delegate is actually invoked, not when the variables were captured:
int factor = 2;
Func<int, int> multiplier = n => n * factor;
factor = 10;
Console.WriteLine (multiplier (3)); // 30
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.
This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 2 years ago.
I have this piece of code:
int i = 0;
foreach(var tile in lib.dic.Values)
{
var ii = i;
var t = tile;
Button b = new Button( () = > { MainStatic.tile = t; } );
Checkbox c = new Checkbox( () = > { lib.arr[ii].b = !lib.arr[ii].b; } );
i++;
}
While the above code works as it should, this piece below:
int i = 0;
foreach(var tile in lib.dic.Values)
{
Button b = new Button( () = > { MainStatic.tile = tile; } );
Checkbox c = new Checkbox( () = > { lib.arr[i].b = !lib.arr[i].b; } );
i++;
}
…will always execute the delegates with the last values of i and tile variables. Why does this happen, and why do I have to make a local copy of those vars, especially non-reference type int i?
Known "issue", please check Eric's blog Closures, captured variables.
Microsof decided to go for a breaking change, and fix it in C# 5.
This is expected: when you make a lambda, compiler creates a closure. It will capture the value of a temporary variable in there, but it would not capture the value of loop variables and other variables that change after creation of the lambda.
The core of the issue is that the delegate creation and execution times are different. The delegate object is created while the loop is running, but it is called well after the loop has completed. At the time the delegate is called, the loop variable has the value that it reached at the time the loop has completed, resulting in the effect that you see (the value does not change, and you see the last value from the loop).
Forgetting to create a temporary variable for use in closures is a mistake so common that popular code analyzers (e.g. ReSharper) warn you about it.
You cannot use loop variables like this because by the time the delegate is executed the loop variable will likely be in its final (end of loop) state as it uses the value of the variable at the time the delete is executed, not created.
You need to make a local copy of the variable to get this to work:
int i = 0;
foreach(var tile in lib.dic.Values)
{
var tileForClosure = tile;
var iForClosure = i;
Button b = new Button( () = > { MainStatic.tile = tileForClosure ; } );
Checkbox c = new Checkbox( () = > { lib.arr[iForClosure].b = !lib.arr[iForClosure].b; } );
i++;
}
By creating a local copy on each loop the value does not change and so your delegate will use the value that you expect.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# - The foreach identifier and closures
From Eric Lippert’s blog: “don’t close over the loop variable”
I'm using a lambda expression as ThreadStart parameter, to run a method in a new thread using Thread class. This is my code:
delegate void del();
static void Do(int i)
{
Console.WriteLine(i);
}
static del CreateLoop(del Do)
{
return () =>
{
while (true)
{
Do();
Thread.Sleep(500);
}
};
}
static void Main(string[] args)
{
int n = 0;
var loop = CreateLoop(() => Do(n));
new Thread(() => loop()).Start();
Thread.Sleep(500);
n = 1;
}
And this is the output:
0
1
1
1
...
How is it possible?
Why if I change the value of my integer variable n, also changes the value of i (Do's parameter)?
You should make a different variable out of it, thus not changing the original value.
After all, all you're really doing is calling that same old 'function', the lambda expression passing the variable i over and over again, which indeed changes. It's nog like you're storing the initial value of the var i somewhere.
var loop = CreateLoop(() => Do(n));
This line is simply creating a new function and assigning it to a variable. This function, among other things, passes the value n to the Do function. But it's not calling the Do function, it's just creating a function which will, when executed, call the Do function.
You then start a new thread which calls the function, etc, but your new thread is still executing Do(n), passing the n variable to Do. That part doesn't change - you've created a function which references a particular place in memory (represented by the variable n) and continues to reference that place in memory even as you change the value which is stored there.
I believe the following would "fix" your code:
var loop = (int x) => () => CreateLoop(() => Do(x));
new Thread(loop(n)).Start();
This passes the value of n to the function represented by loop, but the loop function creates a new place in memory (represented by x) in which to store the value. This new place in memory is not affected by subsequent changes to n. That is to say, the function you've created does not directly reference the place in memory to which n is a pointer.