带有委托的局部变量

本文关键字:局部变量 | 更新日期: 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分配给委托的局部(内部)变量。