Вопрос

Этот явно нет похоже, это не лучшая практика.Может ли кто-нибудь объяснить, почему это не лучшая практика или как это работает?Любые книги или статьи, дающие объяснение, будут оценены по достоинству.

//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";
}

Джон Скит очень хорошо написал об этом в C# в деталях, и отдельный (не такой подробный) разговор здесь.

Обратите внимание, что переменная currentValue теперь находится в куче, а не в стеке - это имеет множество последствий, не в последнюю очередь то, что теперь ее могут использовать различные вызывающие программы.

Это отличается от Java:в Java ценить переменной фиксируется.В C# сама переменная захвачен.

Другие советы

Я полагаю, что больше вопроса, который я задаю, заключается в том, что она работает с локальной переменной [MG Edit:«Ак, игнорируй это...» было добавлено позже]

В этом вся суть;Это реально не локальная переменная больше не является - по крайней мере, не в том смысле, как мы обычно о ней думаем (в стеке и т. д.).Похоже на один, но это не так.

И для информации: «нехорошая практика» — анонимные методы и захваченные переменные на самом деле являются невероятно мощным инструментом, особенно при работе с событиями.Не стесняйтесь использовать их, но если вы пойдете по этому пути, я бы порекомендовал взять книгу Джона, чтобы убедиться, что вы понимаете, что на самом деле происходит.

Вам необходимо зафиксировать значение переменной внутри замыкания/делегата, иначе его можно изменить, как вы видели.

Присвойте currentValue переменной, локальной (внутри) делегата.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top