I was trying to understand the answer for this question Why am I getting wrong results when calling Func<int>? I wrote some sample code. The following code
public static void Main(string[] args)
{
var funcs = new List<Func<string>>();
for(int v=0,i=0;v<3;v++,i++)
{
funcs.Add( new Func<string>(delegate(){return "Hello "+ i++ +" "+v;}) );
}
foreach(var f in funcs)
Console.WriteLine(f());
}
produces
Hello 3 3
Hello 4 3
Hello 5 3
After reading the explanation by Jon Skeet and Eric Lippert I thought I will get
Hello 3 3
Hello 3 3
Hello 3 3
Here both v and i are loop variables, while the value of i is picked up at that instant v is not why is this?. I don't understand the behavior.
Well, you understood Eric and Jon correctly, but you missed one part of your code:
"Hello "+ i++ +" "+v;
^^^
this part increments i for each call
So basically, what happens is similar to this:
i
and v
, and then increment i
i
and v
and since this is the same i
as the previous method call, you will output 4 here, not 3If, on the other hand, you had changed your code by capturing variables inside the loop scope, like this:
for(int v=0,i=0;v<3;v++,i++)
{
int ii = i, vv = v;
funcs.Add( new Func<string>(delegate(){return "Hello "+ ii++ +" "+vv;}) );
}
Then you would get 0, 0
, 1, 1
, and 2, 2
. You're still increasing the ii
variable, you do it after using the captured value in the loop, but then you never use that variable again (each anonymous method gets its own private copy.) thanks @ferosekhanj for the comment
The answer is simple: ++i
is executed inside your delegate, thus incrementing the value each time. The first value will be 3 because that's the value of i after the loop.
Understand that your delegate is not executed inside your for
loop but in the foreach
loop.
the result is correct (how could it not be? ;) ) When you execute the delegate, after the end of the loop, it will use the current value of the i and v variables.
v won't change anymore, v == 3 at the end of the loop. i == 3 too. But your delegate write i to the output, then increment it (i++). Therefore, each time the delegate is executed, i will be incremented, but not v.
This is what you are observing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With