Consider this code snippet and try to guess what y1
and y2
evaluate to
static class Extensions
{
public static Func<T> AsDelegate<T>(this T value)
{
return () => value;
}
}
class Program
{
static void Main(string[] args)
{
new Program();
}
Program()
{
double x = Math.PI;
Func<double> ff = x.AsDelegate();
Func<double> fg = () => x;
x = -Math.PI;
double y1 = ff(); // y1 = 3.141..
double y2 = fg(); // y2 = -3.141..
}
}
You might say -Aha- double is a value type and so the value returned by the extension method is a copy of the main x
. But when you change the above into delegates of classes the results are still different. Example:
class Foo
{
public double x;
}
Program()
{
Foo foo = new Foo() { x=1.0 };
Func<Foo> ff = foo.AsDelegate();
Func<Foo> fg = () => foo;
foo = new Foo() { x = -1.0 };
double y1 = ff().x; // y1 = 1.0
double y2 = fg().x; // y2 = -1.0
}
So the two functions must return two different instances of the same class. It is interesting to consider that ff()
carries with it a reference to local variable foo
, but fg()
does not and it relies on what is in scope currently.
So what happens when these two delegates are passed on to other parts of the code which do not have visibility to foo
instance? Somehow the question of who owns what information (data) is becoming less and less clear when extension methods are combined with delegates.
Void functions are created and used just like value-returning functions except they do not return a value after the function executes. In lieu of a data type, void functions use the keyword "void." A void function performs a task, and then control returns back to the caller--but, it does not return a value.
Function with no argument and no return value: When a function has no arguments, it does not receive any data from the calling function. Similarly, when it does not return a value, the calling function does not receive any data from the called function.
AsDelegate
captures the variable value
(the parameter of AsDelegate
), while () => x
captures the variable x
. So if you change the value of x
, the lambda expression will return a different value. Changing x
doesn't change value
though.
See: Outer Variable Trap
In AsDelegate, we are capturing the the argument "value". the value of this argement is taken as a copy of the value of the variable at the time the method is invoked, and never changes - so we see the original object.
The direct lambda captures the variable foo (not the value of the variable - the variable itself) - thus we do see changes to this.
Basically adding a method call changed the thigh being captured.
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