This function returns two different values depending on the way its called. I understand that Closures close over variables, not over values and I expected the values returned from the second call to be the same regardless of how the function is called
static Func<int, int,int> Sum()
{
var test = 1;
return (op1, op2) =>
{
test = test + 1;
return (op1 + op2) + test;
};
}
Here is the call:
var mFunc = Sum();
Console.WriteLine("Calling Sum(1,1) with Invoke() " + Sum().Invoke(1, 1));
Console.WriteLine("Calling Sum(2,2) with Invoke() " + Sum().Invoke(2, 2));
Console.WriteLine("Calling mFunc(1,1)" + mFunc(1, 1));
Console.WriteLine("Calling mFunc(2,2)" + mFunc(2, 2));
Console.Read();
The result of using Invoke:
4
6
The result of using assigned variable:
4
7
Why does using Invoke changes the closures behavior?
Each time you call Sum
, you're creating a separate test
delegate closing over a new test
variable. The difference isn't "whether or not you use Invoke
" but "whether you're using the result of a new call to Sum()
.
To demonstrate this, you can just change your calls to:
var mFunc = Sum();
Console.WriteLine("Calling mFunc(1,1) with Invoke() " + mFunc.Invoke(1, 1));
Console.WriteLine("Calling mFunc(2,2) with Invoke() " + mFunc.Invoke(2, 2));
Console.WriteLine("----------");
Console.WriteLine("Calling mFunc(1,1)" + mFunc(1, 1));
Console.WriteLine("Calling mFunc(2,2)" + mFunc(2, 2));
Console.Read();
Or you could call Sum
each time instead:
var mFunc = Sum();
Console.WriteLine("Calling Sum()(1,1) with Invoke() " + Sum().Invoke(1, 1));
Console.WriteLine("Calling Sum()(2,2) with Invoke() " + Sum().Invoke(2, 2));
Console.WriteLine("----------");
Console.WriteLine("Calling Sum()(1,1)" + Sum()(1, 1));
Console.WriteLine("Calling Sum()(2,2)" + Sum()(2, 2));
Console.Read();
Of course you don't need any parameters to demonstrate this:
static Action Increment()
{
int test = 1;
return () =>
{
Console.WriteLine(test);
test++;
};
}
Then:
// New delegate for each call
Increment()(); // Prints 1
Increment()(); // Prints 1 again
Increment()(); // Prints 1 again
// Same delegate three times
var action = Increment();
action(); // Prints 1
action(); // Prints 2
action(); // Prints 3
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