A(nother?) question about how variable scope is applied in relation to closures. Here's a minimal example:
public class Foo
{
public string name;
public Foo(string name)
{
this.name = name;
}
}
public class Program
{
static Action getAction(Foo obj)
{
return () => Console.WriteLine(obj.name);
}
static void Main(string[] args)
{
Foo obj1 = new Foo("x1");
Action a = getAction(obj1);
obj1 = new Foo("x2");
a();
}
}
This prints x1
. It can be explained as:
getAction
returns an anonymous function which has a closure enclosing the variable obj
. obj
has the same reference value as obj1
but its relationship with obj1
ends there as the closure encloses only obj
. In other words, whatever value obj1
takes afterwards does not affect the closure. Therefore whenever/however a
gets called (eg. a
gets passed to some other function) it will always print x1
.
Now my questions are:
x2
(eg. closure to enclose an outer scope)? Could it be done (or doesn't it make sense to even attempt)?Let's consider:
static Action getAction(Foo obj)
{
return () => Console.WriteLine(obj.name);
}
The closure is over the parameter obj
; this obj
is a reference passed by value, so if a caller does:
x = someA();
var action = getAction(x);
x = someB(); // not seen by action
then the closure is still over the original value, because the reference (not the object) is copied when passing it to getAction
.
Note that if the caller changes values on the original object, this will be seen by the method:
x = someA();
var action = getAction(x);
x.name = "something else"; // seen by action
Inside the getAction
method, it is basically:
var tmp = new SomeCompilerGeneratedType();
tmp.obj = obj;
return new Action(tmp.SomeCompilerGeneratedMethod);
with:
class SomeCompilerGeneratedType {
public Foo obj;
public void SomeCompilerGeneratedMethod() {
Console.WriteLine(obj.name);
}
}
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