/ / Fonction anonyme et variables locales - c #, .net, compilation, étendue, fonction anonyme

Fonction anonyme et variables locales - c #, .net, compilation, portée, fonction anonyme

Dites que vous avez un bouton sur votre formulaire. Vous avez attaché une fonction anonyme au bouton "s Click un événement:

void Test()
{
int x = 10;
btn.Click += (sender, e) => { MessageBox.Show(x.ToString()); };
}

Cela fonctionne comme prévu et affiche 10; signifie qu'il peut accéder aux variables locales. Ma question est comment et pourquoi? Comment une fonction anonyme accède-t-elle au contexte local?

Le problème que je rencontre est que jebesoin de mettre à niveau (pour ainsi dire) cette fonction anonyme en une fonction régulière (gestionnaire d’événements). Mais cela signifie que je vais perdre l’accès à la variable x. Je ne peux pas "le transmettre en paramètre aussi car je ne pourrai pas le lier à Click événement (incompatibilité de signature). Je peux contourner ce problème en créant des variables globales et tout le reste, mais comment les fonctions anonymes permettent-elles d’accéder à des éléments n’entrant pas dans leur domaine de compétence?

Réponses:

10 pour la réponse № 1

La moitié de la point Les fonctions anonymes sont qu’elles peuvent capturer le contexte dans lequel elles sont spécifiées. C’est extrêmement pratique de pouvoir le faire - c’est la partie "pourquoi".

Pour ce faire, le compilateur crée une nouvelle classe dans les cas où cela est nécessaire. Donc, votre code serait converti en quelque chose comme:

void Test()
{
TestHelper helper = new TestHelper();
helper.x = 10;

btn.Click += helper.Method;
}

private class TestHelper
{
public int x = 10;

public void Method(object sender, EventArgs e)
{
MessageBox.Show(x.ToString());
}
}

Chaque utilisation de x dans Test est converti en un usage de helper.x pour l'instance appropriée. C’est ainsi que les variables de durée de vie différente sont également couvertes. Par exemple, supposons que vous ayez une boucle comme celle-ci:

for (int i = 0; i < 10; i++)
{
int x = i;
// Use with some anonymous function
}

alors il créerait une nouvelle instance de TestHelper pour chaque itération de la boucle ... alors que si x avait été déclaré à l'extérieur Dans la boucle, il n’ya qu’une seule instance que toutes les fonctions anonymes partageraient efficacement.

Quand c'est juste this qui est capturé, le compilateur crée une instanceméthode dans la classe existante au lieu de créer une classe auxiliaire. Quand il existe différentes portées avec potentiellement plusieurs fonctions anonymes qui capturent une variété de variables, les choses peuvent devenir beaucoup plus compliquées, certaines classes auxiliaires ayant des références à des instances d'autres classes auxiliaires, etc.