gpt4 book ai didi

C# 闭包变量作用域

转载 作者:可可西里 更新时间:2023-11-01 08:59:11 39 4
gpt4 key购买 nike

关于闭包如何应用变量范围的(另一个?)问题。这是一个最小的例子:

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();
}
}

这会打印出 x1。可以解释为:

getAction 返回一个匿名函数,它有一个包含变量 obj 的闭包。 objobj1 具有相同的引用 value 但它与 obj1 的关系到此为止,因为闭包仅包含 对象。换句话说,obj1 之后取的任何值都不会影响闭包。因此无论何时/无论如何 a 被调用(例如 a 被传递给其他一些函数)它总是打印 x1

现在我的问题是:

  1. 以上解释是否正确?
  2. 我没有想到具体的场景,但如果我们希望程序打印 x2(例如闭包以包含外部范围)怎么办?可以完成吗(或者甚至尝试都没有意义)?

最佳答案

让我们考虑一下:

static Action getAction(Foo obj)
{
return () => Console.WriteLine(obj.name);
}

闭包覆盖了参数 obj;此 obj 是按值传递的引用,因此如果调用者这样做:

x = someA();
var action = getAction(x);
x = someB(); // not seen by action

然后闭包仍然在 原始 值之上,因为引用(不是对象)在传递给 getAction 时被复制

请注意,如果调用者更改原始对象的值,方法将看到:

x = someA();
var action = getAction(x);
x.name = "something else"; // seen by action

getAction 方法内部,它基本上是:

var tmp = new SomeCompilerGeneratedType();
tmp.obj = obj;
return new Action(tmp.SomeCompilerGeneratedMethod);

与:

class SomeCompilerGeneratedType {
public Foo obj;
public void SomeCompilerGeneratedMethod() {
Console.WriteLine(obj.name);
}
}

关于C# 闭包变量作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32580033/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com