Domanda

Questo chiaramente non è appare come se non fosse una buona pratica. Qualcuno può spiegare perché non sarebbe una buona pratica o come funziona? Qualsiasi libro o articolo che fornisca una spiegazione sarebbe apprezzato.

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

}

Il valore che viene emesso è il secondo valore " Modified " . Quale parte della magia del compilatore sta facendo funzionare questo? È semplice come tenere traccia del valore nell'heap e recuperarlo di nuovo in seguito?

[Modifica]: dati alcuni dei commenti, cambiando la frase originale in alcuni ...

È stato utile?

Soluzione

currentValue non è più una variabile locale: è una variabile catturata . Questo si compila in qualcosa del tipo:

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 ne ha davvero ben scritto in C # in profondità e un altro ( discussione non così dettagliata) qui .

Nota che la variabile currentValue è ora nell'heap, non nello stack - questo ha molte implicazioni, non ultimo che ora può essere utilizzato da vari chiamanti.

Questo è diverso da java: in java viene catturato il valore di una variabile. In C #, viene catturata la variabile stessa .

Altri suggerimenti

  

Suppongo che la domanda che sto ponendo sia: come funziona con una variabile locale   [Modifica MG: " Ack - ignora questo ... " è stato aggiunto in seguito]

Questo è il punto; in realtà non è più una variabile locale, almeno non in termini di come normalmente le pensiamo (in pila ecc.). Sembra uno, ma non lo è.

E per informazioni, non "buona pratica" - i metodi anonimi e le variabili acquisite sono in realtà uno strumento incredibilmente potente, specialmente quando si lavora con eventi. Sentiti libero di usarli, ma se stai seguendo questa strada, ti consiglio di prendere il libro di Jon per assicurarti di capire cosa sta realmente accadendo.

Devi catturare il valore della variabile all'interno della chiusura / delegato, altrimenti può essere modificata, come hai visto.

Assegna currentValue a una variabile locale (interna) al delegato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top