带委托的局部变量
时间:2020-03-06 14:52:25 来源:igfitidea点击:
显然,这似乎不是最佳实践。有人可以解释为什么它不是最佳实践或者它如何运作吗?任何提供解释的书或者文章将不胜感激。
//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)在Cin Depth上对此进行了很好的撰写,在这里进行了单独的(不那么详细)讨论。
请注意,变量currentValue现在位于堆上,而不是堆栈上,这具有很多含义,尤其是它现在可以被各种调用程序使用。
这与Java不同:在Java中,变量的值被捕获。在C#中,变量本身被捕获。
我们需要在闭包/委托中捕获变量的值,否则可以像我们看到的那样对其进行修改。
将currentValue分配给委托本地(内部)的变量。
I suppose more the question I am asking is that how is it working with a local variable [MG edit: "Ack - ignore this..." was added afterwards]
这就是我想说的;至少在我们通常如何看待它们(在堆栈上等)方面,它实际上至少不再是局部变量。它看起来像一个,但事实并非如此。
对于信息来说,"不好的做法"匿名方法和捕获的变量实际上是一个非常强大的工具,尤其是在处理事件时。可以随意使用它们,但是如果我们沿这条路线走,我建议我们拿起乔恩的书,以确保我们了解实际发生的情况。