Question

Cette n'est clairement pas comme si ce n'était pas une bonne pratique. Quelqu'un peut-il expliquer pourquoi ce ne serait pas une meilleure pratique ou comment cela fonctionne? Tout livre ou article fournissant une explication serait apprécié.

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

}

La valeur en sortie est la deuxième valeur "Modifié" . Quelle partie de la magie du compilateur fait ce travail? Est-ce aussi simple que de garder une trace de la valeur sur le tas et de la récupérer ultérieurement?

[Éditer]: En fonction de certains commentaires, en modifiant la phrase d'origine en ...

Était-ce utile?

La solution

currentValue n'est plus une variable locale: c'est une variable capturée . Cela compile quelque chose comme:

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 a une très bonne rédaction de ceci dans C # en profondeur , et un document séparé ( pas aussi détaillée) discussion ici .

Notez que la variable currentValue est maintenant sur le tas, pas sur la pile - cela a de nombreuses implications, sans oublier qu'elle peut maintenant être utilisée par différents appelants.

Cela diffère de java: en java, la valeur d'une variable est capturée. En C #, la variable elle-même est capturée.

Autres conseils

  

Je suppose que plus la question que je pose est que comment ça marche avec une variable locale   [Modification MG: "Ack - ignore this ..." a été ajouté ensuite]

C'est le point; ce n'est vraiment pas une variable locale, du moins pas en ce qui concerne notre façon de penser (sur la pile, etc.). Cela ressemble à un, mais ça ne l’est pas.

Et pour info, il ne s'agit pas de "bonnes pratiques". - les méthodes anonymes et les variables capturées sont en fait un outil incroyablement puissant, en particulier lorsque vous travaillez avec des événements. N'hésitez pas à les utiliser, mais si vous suivez cette voie, je vous conseillerais de prendre le livre de Jon pour vous assurer de bien comprendre ce qui se passe réellement.

Vous devez capturer la valeur de la variable dans la clôture / le délégué, sinon elle peut être modifiée, comme vous l'avez vu.

Affectez currentValue à une variable locale (interne) au délégué.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top