124 votes

Assigner du code à une variable

Est-il possible de créer une variable et lui assigner une ligne de code, comme ceci :

ButtonClicked = (MessageBox.Show("Bonjour, le monde !"));

... ainsi, lorsque j'utilise la variable, elle exécutera la ligne de code.

89voto

Grant Winney Points 25981

Vous pourriez l'attribuer à une Action comme ceci :

var ButtonClicked = new Action(() => MessageBox.Show("hi"));

Ensuite, appelez-le :

ButtonClicked();

Pour compléter (en ce qui concerne les différents commentaires)...

Comme l'a dit Erik, vous pourriez exécuter plusieurs lignes de code :

var ButtonClicked = new Action(() =>
{
    MessageBox.Show("hi");

    MessageBox.Show("something else");  // quelque chose de plus utile qu'une autre popup ;)
});

Comme l'a indiqué Tim, vous pourriez omettre le mot-clé Action

Action ButtonClicked = () => MessageBox.Show("hi");

Action ButtonClicked = () =>
{
    // plusieurs lignes de code
};

Pour répondre au commentaire de KRyan, concernant les parenthèses vides, cela représente la liste des paramètres que vous souhaitez pouvoir envoyer à l'Action (dans ce cas, aucun).

Par exemple, si vous vouliez spécifier le message à afficher, vous pourriez ajouter "message" en tant que paramètre (notez que j'ai changé Action en Action afin de spécifier un seul paramètre de type chaîne):

Action ButtonClicked = (message) => MessageBox.Show(message);

ButtonClicked("hello world!");

51voto

user3439065 Points 713

Dans votre cas, vous voulez utiliser un délégué.

Voyons comment fonctionne un délégué et comment nous pouvons arriver à une forme plus simple en comprenant son concept:

// Créer une fonction normale
void OnButtonClick()
{
    MessageBox.Show("Bonjour le monde!");
}
// Maintenant nous créons un délégué appelé ButtonClick
delegate void ButtonClick();

Vous voyez, le délégué prend la forme d'une fonction normale mais sans aucun argument (il pourrait prendre n'importe quel nombre d'arguments comme n'importe quelle autre méthode, mais pour simplifier, il ne le fait pas).

Maintenant, utilisons ce que nous avons; nous allons définir le délégué comme nous définissons n'importe quelle autre variable:

ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);

Nous avons simplement créé une nouvelle variable appelée ButtonClicked, qui a un type de ButtonClick (qui est un délégué) et qui, lorsqu'elle est utilisée, exécutera la méthode dans la méthode OnButtonClick().
Pour l'utiliser, nous appelons simplement: ButtonClicked();

Ainsi, tout le code serait:

delegate void ButtonClick();

void OnButtonClick()
{
    MessageBox.Show("Bonjour le monde!");
}

void Foo()
{
    ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
    ButtonClicked(); // Exécute la fonction.
}  

À partir de là, nous pouvons passer aux expressions lambda et voir comment elles pourraient être utiles dans votre cas:
Il existe de nombreux délégués déjà définis par les bibliothèques .NET, avec certains comme Action, qui n'acceptent aucun paramètre et ne renvoient aucune valeur. Il est défini comme public delegate void Action();
Vous pouvez toujours l'utiliser selon vos besoins au lieu de devoir définir un nouveau délégué à chaque fois. Dans le contexte précédent par exemple, vous auriez simplement pu écrire

Action ButtonClicked = new Action(OnButtonClick);
ButtonClicked();

ce qui aurait fait la même chose.
Maintenant que vous avez vu différentes façons d'utiliser les délégués, utilisons notre première expression lambda. Les expressions lambda sont des fonctions anonymes; elles sont donc des fonctions normales mais sans nom. Elles prennent ces formes:

x => DoSomethingWithX(x);
(x) => DoSomethingWithX(x);
(x,y) => DoSometingWithXY(x,y);
() => Console.WriteLine("Je n'ai pas de paramètres!");

Dans notre cas, nous n'avons pas de paramètres, nous utiliserons donc la dernière expression. Nous pouvons l'utiliser comme la fonction OnButtonClick, mais nous avons l'avantage de ne pas avoir de fonction nommée. Nous pouvons plutôt faire quelque chose comme ceci:

Action ButtonClicked = new Action( () => MessageBox.Show("Bonjour le monde!") );

ou encore plus simplement,

Action ButtonClicked = () => MessageBox.Show("Bonjour le monde!");

ensuite, il suffit d'appeler ButtonClicked(); Bien sûr, vous pouvez également avoir plusieurs lignes de code, mais je ne veux pas vous embrouiller davantage. Ça ressemblerait à ceci cependant:

Action ButtonClicked = () => 
{
    MessageBox.Show("Bonjour le monde!");
};
ButtonClicked();

Vous pouvez également expérimenter, par exemple, vous pouvez exécuter une fonction de cette manière:

new Action(() => MessageBox.Show("Bonjour le monde!"))();

Désolé pour le long message, j'espère qu'il n'était pas trop confus :)

ÉDIT: J'ai oublié de mentionner qu'une forme alternative qui, bien que rarement utilisée, pourrait rendre les expressions lambda plus faciles à comprendre:

new Action(delegate() {
    Console.WriteLine("Je suis sans paramètre");
})();

Également, en utilisant des génériques:

// Définit un délégué qui a un paramètre de type chaîne. Vous pouvez passer autant de paramètres que vous le souhaitez.
new Action(delegate(string x) {
    Console.WriteLine(x);
})("Je suis un paramètre de chaîne!");

À son tour, vous pourriez utiliser des expressions lambda, mais vous n'avez pas besoin (mais cela pourrait être le cas dans certains cas) de définir le type du paramètre, par exemple, le code ci-dessus pourrait simplement être écrit comme suit:

new Action(x => {
    Console.WriteLine(x);
})("Je suis un paramètre de chaîne!");

ou:

new Action(x => Console.WriteLine(x))("Je suis un paramètre de chaîne!");

ÉDIT2:
Action est une représentation de public void delegate Action(string obj);
Action est une représentation de public void delegate Action(string obj, string obj2);
En général, Action est une représentation de public void delegate Action(T obj);

ÉDIT3: Je sais que le message est là depuis un certain temps, mais je trouve cela vraiment cool de ne pas le mentionner: Vous pouvez faire ceci, ce qui est principalement lié à votre question:

dynamic uneFonction = (Func)MessageBox.Show;
uneFonction("Bonjour, le monde!");

ou simplement:

Func uneFonction = MessageBox.Show;
uneFonction("Bonjour, le monde!");

7voto

Servy Points 93720

La classe Lazy est spécifiquement conçue pour représenter une valeur qui ne sera calculée que lorsque vous le demanderez. Vous la construisez en fournissant une méthode qui définit comment elle doit être construite, mais elle exécutera cette méthode pas plus d'une fois (même en présence de plusieurs threads demandant la valeur) et renverra simplement la valeur déjà construite pour toute demande supplémentaire :

var foo = new Lazy(()=>MessageBox.Show("Hello, World!"));

var result = foo.Value;

4voto

Zaccone Points 124

La manière dont je comprends votre question, c'est dans le contexte des contrôles GUI?

Si c'est en WPF, jetez un œil à la façon "correcte" de gérer les commandes des contrôles: http://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx

... mais cela peut être fastidieux et excessif. Pour un cas général plus simple, vous pourriez rechercher un gestionnaire d'événements, comme:

myButton.Click += (o, e) => MessageBox.Show("Bonjour, tout le monde!");

Ce gestionnaire d'événements peut être géré de diverses manières. L'exemple ci-dessus utilise une fonction anonyme, mais vous pourriez également faire :

Action direBonjour = (o, e) => MessageBox.Show("Bonjour, tout le monde");
myButton.Click += new RoutedEventHandler(direBonjour);

... exactement comme vous le demandiez, avec une fonction (ou ici, "Action", car elle renvoie void) attribuée à une variable.

1voto

Amir Saniyan Points 2406

Vous pouvez attribuer du code C# à une variable, le compiler à l'exécution et exécuter le code :

  • Écrivez votre code :

    // Assignez du code C# à la variable code.
    string code = @"
    using System;
    
    namespace First
    {
        public class Program
        {
            public static void Main()
            {
                " +
                "Console.WriteLine(\"Bonjour le monde !\");"
                + @"
            }
        }
    }
    ";
  • Créez le fournisseur et les paramètres du compilateur :

    CSharpCodeProvider provider = new CSharpCodeProvider();
    CompilerParameters parameters = new CompilerParameters();
  • Définissez les paramètres du compilateur :

    // Référence à la bibliothèque System.Drawing
    parameters.ReferencedAssemblies.Add("System.Drawing.dll");
    // True - génération en mémoire, false - génération de fichier externe
    parameters.GenerateInMemory = true;
    // True - génération de fichier exe, false - génération de fichier dll
    parameters.GenerateExecutable = true;
  • Compiler l'assembly :

    CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
  • Vérifiez les erreurs :

    if (results.Errors.HasErrors)
    {
            StringBuilder sb = new StringBuilder();
    
            foreach (CompilerError error in results.Errors)
            {
                    sb.AppendLine(String.Format("Erreur ({0}): {1}", error.ErrorNumber, error.ErrorText));
            }
    
            throw new InvalidOperationException(sb.ToString());
    }
  • Obtenez l'assembly, le type et la méthode Main :

    Assembly assembly = results.CompiledAssembly;
    Type program = assembly.GetType("First.Program");
    MethodInfo main = program.GetMethod("Main");
  • Exécutez-le :

    main.Invoke(null, null);

Référence :

http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X