创建闭包时,编译器会为您创建一个类型,该类型具有每个捕获变量的成员。在您的示例中,编译器将生成如下内容:
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
public string foo;
public void <Main>b__0()
{
Console.WriteLine(this.foo);
}
}
为您的委托提供对此类型的引用,以便以后可以使用捕获的变量。不幸的是,本地实例foo
也被更改为指向此处,因此本地的任何更改都会影响委托,因为它们使用相同的对象。
如您所见,持久性foo
是由公共字段而不是属性处理的,因此在当前实现中甚至没有不变性选项。我认为你想要的必须是这样的:
var foo = "hello";
Action bar = [readonly foo]() => Console.WriteLine(foo);
bar();
foo = "goodbye";
bar();
请原谅笨拙的语法,但想法是表示foo
以一种方式捕获readonly
它,然后提示编译器输出这个生成的类型:
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
public readonly string foo;
public <>c__DisplayClass1(string foo)
{
this.foo = foo;
}
public void <Main>b__0()
{
Console.WriteLine(this.foo);
}
}
这将以某种方式为您提供您想要的东西,但需要更新编译器。