使用Delegates的局部变量

显然,这似乎不是最佳做法。 有人可以解释为什么它不是最佳实践或如何工作? 任何提供解释的书籍或文章将不胜感激。

//The constructor public Page_Index() { //create a local value string currentValue = "This is the FIRST value"; //use the local variable in a delegate that fires later this.Load += delegate(object sender, EventArgs e) { Response.Write(currentValue); }; //change it again currentValue = "This is the MODIFIED value"; } 

输出的值是第二个值“已修改” 。 编译魔术的哪个部分使这个工作? 这跟跟踪堆上的值并稍后再次检索它一样简单吗?

[编辑]:鉴于一些评论,改变原来的一些句子……

currentValue不再是局部变量:它是一个捕获的变量。 这编译成如下:

 class Foo { public string currentValue; // yes, it is a field public void SomeMethod(object sender, EventArgs e) { Response.Write(currentValue); } } ... public Page_Index() { Foo foo = new Foo(); foo.currentValue = "This is the FIRST value"; this.Load += foo.SomeMethod; foo.currentValue = "This is the MODIFIED value"; } 

Jon Skeet 在深度的C#中有一个非常好的写作,在这里有一个单独的(不详细的)讨论。

请注意,变量currentValue现在位于堆上,而不是堆栈 – 这有很多含义,尤其是它现在可以被各种调用者使用。

这与java不同:在java中捕获变量的 。 在C#中,捕获变量本身

我想更多我问的问题是它是如何使用局部变量[MG编辑:“Ack – 忽略这个…”之后又添加了]

这就是重点; 它真的不再是局部变量 – 至少,不是我们通常如何看待它们(在堆栈等)。 它看起来像一个,但事实并非如此。

而对于信息,重新“不好的做法” – 匿名方法和捕获的变量实际上是一个非常强大的工具, 尤其是在处理事件时。 随意使用它们,但是如果你沿着这条路走下去,我会建议你拿起Jon的书来确保你理解实际发生的事情。

您需要在闭包/委托中捕获变量的值,否则可以像您看到的那样对其进行修改。

将currentValue分配给委托的本地(内部)变量。