提问人:hugoware 提问时间:9/29/2008 最后编辑:trincothugoware 更新时间:6/13/2021 访问量:12877
具有委托的局部变量
Local variables with 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";
}
输出的值是第二个值“Modified”。编译器魔力的哪一部分使这项工作得以实现?这是否就像跟踪堆上的值并在以后再次检索它一样简单?
[编辑]:鉴于一些评论,将原句更改为一些...
答:
32赞
Marc Gravell
9/29/2008
#1
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# 中,变量本身是被捕获的。
评论
0赞
Jon Skeet
9/29/2008
除了用 C# 深入编写它(感谢插件!)之外,我还有一篇文章比较了 C# 和 Java 闭包,并解释了为什么它们很好: csharpindepth.com/Articles/Chapter5/Closures.aspx
0赞
Marc Gravell
9/29/2008
啊 - 当你写那条评论时,我正在编辑上面的内容以包含它。将值加倍;-p
0赞
chiccodoro
10/7/2010
@Mark:为了稍微改善你的回答,你能在最后一句话中将“变量值”换成“变量值”吗?由于该变量被称为“currentValue”,它可能会使读者(像我一样)感到困惑,首先认为斜体“值”指的是变量的名称(“哪个变量?那个叫做值 ")
1赞
Prashant Cholachagudda
10/7/2010
我推荐 Eric Lippert 最近的博客文章,关于如何存储和管理变量。blogs.msdn.com/b/ericlippert/archive/2010/09/30/......
0赞
leppie
9/29/2008
#2
您需要在闭包/委托中捕获变量的值,否则可以对其进行修改,就像您看到的那样。
将 currentValue 分配给委托的变量 local(内部)。
2赞
Marc Gravell
9/29/2008
#3
我想我要问的更多问题是它如何使用局部变量 [MG编辑:“哎呀 - 忽略这个......”事后添加]
这就是重点;它真的不再是一个局部变量了——至少,不是我们通常认为它们的方式(在堆栈等上)。它看起来像一个,但事实并非如此。
对于信息,re“不好的做法” - 匿名方法和捕获的变量实际上是一个非常强大的工具,尤其是在处理事件时。随意使用它们,但如果你要走这条路,我建议你拿起乔恩的书,以确保你了解实际发生的事情。
评论