c# - usa - Variables locales con delegados
tipos de datos en c# visual studio (3)
Supongo que más la pregunta que estoy haciendo es cómo está trabajando con una variable local [MG edit: "Ack - ignore esto ..." se agregó después]
Ese es el punto; ya no es una variable local, al menos, no en términos de cómo pensamos normalmente en ellos (en la pila, etc.). Parece uno, pero no lo es.
Y para obtener información, "no es una buena práctica": los métodos anónimos y las variables capturadas son en realidad una herramienta increíblemente poderosa, especialmente cuando se trabaja con eventos. Siéntase libre de usarlos, pero si va por esta ruta, le recomendaría recoger el libro de Jon para asegurarse de que entienda lo que realmente está sucediendo.
Esto claramente no parece que no sería una mejor práctica. ¿Alguien puede explicar por qué no sería una buena práctica o cómo funciona? Cualquier libro o artículo que proporcione una explicación sería apreciado.
//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";
}
El valor que se genera es el segundo valor "Modificado" . ¿Qué parte de la magia del compilador está haciendo que esto funcione? ¿Es esto tan simple como hacer un seguimiento del valor en el montón y recuperarlo más tarde?
[Editar]: dado algunos de los comentarios, cambiar la oración original algunos ...
Debe capturar el valor de la variable dentro del cierre / delegado, de lo contrario se puede modificar, como lo vio.
Asigna currentValue a una variable local (inside) al delegado.
currentValue ya no es una variable local: es una variable capturada . Esto compila a algo como:
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 tiene una muy buena redacción de esto en C # en profundidad , y una discusión separada (no tan detallada) aquí .
Tenga en cuenta que la variable currentValue ahora está en el montón, no en la pila; esto tiene muchas implicaciones, sobre todo porque ahora puede ser utilizado por varias personas que llaman.
Esto es diferente a java: en java se captura el valor de una variable. En C #, la variable en sí es capturada.