Let me apologize in advance - I'm probably butchering the terminology. I have a vague understanding of what a closure is, but can't explain the behaviour I'm seeing. At least, I think it's a closure issue. I've searched online, but haven't found the right keywords to get what I want.
Specifically - I have two blocks of code that are REALLY SIMILAR (at least to my eyes). First:
static void Main(string[] args)
{
Action x1 = GetWorker(0);
Action x2 = GetWorker(1);
}
static Action GetWorker(int k)
{
int count = 0;
// Each Action delegate has it's own 'captured' count variable
return k == 0 ? (Action)(() => Console.WriteLine("Working 1 - {0}",count++))
: (Action)(() => Console.WriteLine("Working 2 - {0}",count++));
}
If you run this code and invoke x1() and x2() you'll see that they maintain a separate 'count' value.
foreach(var i in Enumerable.Range(0,4))
{
x1(); x2();
}
Outputs:
Working 1 - 0
Working 2 - 0
Working 1 - 1
Working 2 - 1
Working 1 - 2
Working 2 - 2
Working 1 - 3
Working 2 - 3
That makes sense to me and matches the explanations I've read. Behind the scenes a class is created for each delegate/action and the class is given a field to hold the value of 'count'. I went to bed feeling smart!
BUT THEN - I tried this very similar code:
// x3 and x4 *share* the same 'captured' count variable
Action x3 = () => Console.WriteLine("Working 3 - {0}", count++);
Action x4 = () => Console.WriteLine("Working 4 - {0}", count++);
And (like the comment says) the behavior is completely different here. x3() and x4() seem to have the SAME count value!
Working 3 - 0
Working 4 - 1
Working 3 - 2
Working 4 - 3
Working 3 - 4
Working 4 - 5
Working 3 - 6
Working 4 - 7
I can see what's happening - but I don't really get why they are treated differently. In my head - I liked that original behaviour I was seeing, but the later example confuses me. I hope that makes sense. Thanks