带有委托的局部变量
本文关键字:局部变量 | 更新日期: 2023-09-27 17:48:51
这个显然不是似乎不是最佳实践。有人能解释一下为什么这不是最佳实践,或者这是如何运作的吗?任何提供解释的书籍或文章都将不胜感激。
//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";
}
输出的值是第二个值"Modified"。编译器的魔力是什么?这和跟踪堆上的值并稍后再次检索它一样简单吗?
[编辑]:给出一些评论,将原句改一些。。。
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编辑:之后添加了"确认-忽略此…"]
这就是重点;它真的不再是局部变量了——至少,不是从我们通常如何看待它们(在堆栈上等)的角度来看的。它看起来像一个,但事实并非如此。
关于信息,"不是好的做法"-匿名方法和捕获的变量实际上是一个非常强大的工具,尤其是在处理事件时。可以随意使用它们,但如果你要走这条路,我建议你拿起乔恩的书,确保你了解实际发生了什么。
您需要在闭包/委托中捕获变量的值,否则可以对其进行修改,如您所见。
将currentValue分配给委托的局部(内部)变量。