I\'m reading Jon Skeet\'s C# in Depth.
On page 156 he has an example, Listing 5.13 \"Capturing multiple variable instantiations with multiple delegates\".
It sounds like you've worked out the answer - you don't get a new index
instance each time round the loop. If you consider the ways you're allowed to modify the index
value inside the loop - eg. you can increment it if you want to skip items, set it back to zero in some cases, or anything else you like - it should be clear that you've only got one instance of index
, not a new one for every iteration.
On the other hand, a new counter
is created on every iteration - if you made a change to it at the bottom of that loop, it would have no effect on the counter
variable that the next iteration uses.
foreach
loops used to reuse their loop variable, in the same way as for
loops, and this was a common gotcha for people - see Is there a reason for C#'s reuse of the variable in a foreach?
Eric Lippert explains that they've changed foreach
in C# 5 to get a new variable every time, and also that they're leaving for
as-is.
As far as I understood closures. It is the anonymous delegate which triggers the creation of a class for the variables involved in the delegates code block. Consider the following code:
class SomeClass
{
public int counter;
public void DoSomething()
{
Console.WriteLine(counter);
counter++;
}
}
//...
List<ThreadStart> list = new List<ThreadStart>();
for (int index = 0; index < 5; index++)
{
var instance = new SomeClass { counter = index * 10 };
list.Add(instance.DoSomething);
}
foreach (ThreadStart t in list)
{
t();
}
This code does exactly the same as in the original example. The variable instance
is defined inside of the for loop, so its scope ends at every iteration, however it is not freed by the garbage collector since it is referenced by list
. This is the reason why a class is created in case of anonymous delegates. You cannot do it otherwise.