+1 pour la rare combinaison d'être nouveau dans le codage et de poser une bonne question: vous comprenez ce que vous voulez faire et l'expliquez bien, vous ne connaissez tout simplement pas le terme pour cela, vous ne pouvez donc pas le trouver par vous-même.
stackoverflow.com/questions/6187944/… vérifiez ceci, je pense qu'il y a suffisamment d'explications dont vous aurez besoin. Asp fonctionne presque comme des winforms dans ce domaine.
CSharpie
Cela ressemble beaucoup à des blocs dans Objective-c
Par souci d'exhaustivité (en ce qui concerne les différents commentaires) ...
Comme l'a déclaré Erik, vous pouvez exécuter plusieurs lignes de code:
varButtonClicked=newAction(()=>{MessageBox.Show("hi");MessageBox.Show("something else");// something more useful than another popup ;)});
Comme Tim l'a dit, vous pouvez omettre le Actionmot - clé
ActionButtonClicked=()=>MessageBox.Show("hi");ActionButtonClicked=()=>{// multiple lines of code};
Pour répondre au commentaire de KRyan, concernant les parenthèses vides, qui représente la liste des paramètres que vous voulez pouvoir envoyer à l'action (dans ce cas, aucun) .
Si, par exemple, que vous vouliez spécifier le message à afficher, vous pouvez ajouter « message » en tant que paramètre (notez que je l' ai changé Actionpour afin de spécifier un seul paramètre de chaîne) :Action<string>
Action ButtonClicked = () => MessageBox.Show("hi");est équivalent et IMO plus agréable (ajoutez des parens si vous préférez)
Tim S.
1
Il est également possible que l'action se résout à plus d'une seule ligne de code.
Erik Philips
2
@CSharpie Je ne suis pas sûr que cette hypothèse soit utile pour l'OP.
Erik Philips
2
@CSharpie Pourquoi l'OP n'a-t-il pas pu l'utiliser WinForms?
vivat pisces
2
@CSharpie Je vois ce que vous dites. S'il l'attache réellement à un Button.Clickévénement et ne le stocke pas dans une variable qu'il a nommée ButtonClicked.
vivat pisces
51
Dans votre cas, vous souhaitez utiliser un fichier delegate.
Voyons comment fonctionne un délégué et comment nous pouvons obtenir une forme plus simple en comprenant son concept:
// Create a normal functionvoidOnButtonClick(){MessageBox.Show("Hello World!");}// Now we create a delegate called ButtonClickdelegatevoidButtonClick();
Vous voyez, le délégué prend la forme d'une fonction normale mais sans aucun argument (il peut prendre n'importe quelle quantité d'arguments comme n'importe quelle autre méthode, mais pour des raisons de simplicité, ce n'est pas le cas).
Maintenant, utilisons ce que nous avons; nous définirons le délégué comme nous définissons toute autre variable:
Nous avons essentiellement 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();
Donc, tout le code serait:
delegatevoidButtonClick();voidOnButtonClick(){MessageBox.Show("Hello World!");}voidFoo(){ButtonClickButtonClicked=newButtonClick(OnButtonClick);ButtonClicked();// Execute the function.}
À partir de là, nous pouvons passer aux expressions lambda et voir comment elles pourraient être utiles dans votre situation:
il existe de nombreux délégués déjà définis par les bibliothèques .NET, 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 définir un nouveau délégué à chaque fois. Dans le contexte précédent par exemple, vous auriez pu juste écrire
qui aurait fait de même.
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; donc, ce sont des fonctions normales mais sans nom. Ils sont de ces formes:
x =>DoSomethingWithX(x);(x)=>DoSomethingWithX(x);(x,y)=>DoSometingWithXY(x,y);()=>Console.WriteLine("I do not have parameters!");
Dans notre cas, nous n'avons aucun paramètre donc nous utiliserons 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 à la place faire quelque chose comme ceci:
alors appelez simplement ButtonClicked();Bien sûr, vous pouvez également avoir plusieurs lignes de code, mais je ne veux pas vous embrouiller davantage. Cela ressemblerait à ceci:
Vous pouvez également jouer, par exemple, vous pouvez exécuter une fonction comme celle-ci:
newAction(()=>MessageBox.Show("Hello World!"))();
Désolé pour le long post, j'espère que ce n'était pas trop déroutant :)
EDIT: J'ai oublié de mentionner qu'une forme alternative qui, même si elle n'est pas souvent utilisée, pourrait rendre les expressions lambda plus faciles à comprendre:
newAction(delegate(){Console.WriteLine("I am parameterless");})();
Aussi, en utilisant des génériques:
// Defines a delegate that has one parameter of type string. You could pass as many parameters as you want.newAction<string>(delegate(string x){Console.WriteLine(x);})("I am a string parameter!");
À son tour, vous pouvez utiliser des expressions lambda, mais vous n'avez pas besoin (mais vous pourriez dans certains cas) définir le type du paramètre, par exemple, le code ci-dessus pourrait simplement être écrit comme suit:
newAction<string>(x =>{Console.WriteLine(x);})("I am a string parameter!");
ou:
newAction<string>(x =>Console.WriteLine(x))("I am a string parameter!");
EDIT2: Action<string>est une représentation de public void delegate Action(string obj); Action<string,string>est une représentation de public void delegate Action(string obj, string obj2);
En général, Action<T>est une représentation depublic void delegate Action<T>(T obj);
EDIT3: Je sais que le message est ici depuis un moment, mais je pense que c'est vraiment cool de ne pas le mentionner: vous pouvez le faire, ce qui est principalement lié à votre question:
La Lazyclasse est spécifiquement conçue pour représenter une valeur qui ne sera pas calculée tant que vous ne l'aurez pas demandée. Vous la construisez en fournissant une méthode qui définit comment elle doit être construite, mais elle gérera l'exécution de cette méthode pas plus d'une fois (même face à plusieurs threads demandant la valeur) et renvoyant simplement la valeur déjà construite pour toute demande supplémentaire:
var foo =newLazy<DialogResult>(()=>MessageBox.Show("Hello, World!"));var result = foo.Value;
Rappelez-vous que cela Lazydoit être utilisé pour les valeurs qui nécessitent beaucoup de puissance de traitement, et que vous ne devez pas les utiliser pour l'interaction (car la sémantique de .Valueest qu'elle renvoie une valeur, similaire à une propriété, pas une action (interactive)). Un délégué doit être utilisé pour de telles actions à la place.
Abel
1
@Abel Non, ce n'est pas pour les valeurs qui nécessitent beaucoup de puissance de traitement, c'est pour toute valeur dont vous souhaitez différer l'initialisation jusqu'à ce qu'elle soit demandée, sans jamais initialiser cette valeur plus d'une fois. Ici, la valeur de Valueest utilisée; c'est le DialogResultreçu de l'affichage de la boîte de message. La principale différence entre cette solution et l'utilisation d'un délégué est de savoir si la valeur doit être recalculée à chaque fois qu'elle est demandée ou non. Mon interprétation des exigences était que cela initialise conceptuellement une valeur, pas une opération à répéter.
Servy
Lazypeut facilement être mal utilisé. Il a une surcharge en soi, l'utiliser "juste" pour différer une petite tâche entraînera plus de surcharge qu'il n'en gagne. Afficher les boîtes de message d'une propriété est une mauvaise pratique (imo) en général, indépendamment de Lazy. Btw, de MSDN, je cite: "Utilisez l'initialisation paresseuse pour différer la création d'un objet volumineux ou gourmand en ressources" . Vous pouvez être en désaccord avec cela, mais c'est pour cela qu'il a été conçu à l'origine.
Abel
1
@Abel La surcharge de performance Lazydans un contexte comme celui-ci est certainement négligeable; cela pâlira par rapport au temps passé à attendre qu'un humain clique sur une boîte de message. Cela se résume principalement aux exigences réelles de l'application sous-jacente; le caractère vague de la question rend impossible une réponse objectivement correcte. Ceci est une interprétation de la question. Quant à faire beaucoup de travail dans une propriété getter étant mauvais; apparemment, vous êtes fondamentalement opposé à la conception entière de Lazy. Vous êtes les bienvenus à cette opinion.
Servy
Désolé, vous devez m'avoir mal compris. Certes, MessageBox la surcharge est négligeable (je n'utiliserais tout simplement pas l'interface utilisateur à l'intérieur d'une propriété). Je voulais dire de petites tâches en général (comme le report 2 + 3 * 4 / i), où la surcharge de création de la fermeture est plus grande que le calcul lui-même. Et je pense que j'adhère pleinement Lazy, en fait nous l'utilisons beaucoup en F # (un peu moins en C #) et nous avons appris à la dure qu'il faut faire attention, en particulier. dans le respect de la performance.
Abel
4
La façon dont je lis votre question, c'est dans le contexte des contrôles GUI?
Ce gestionnaire d'événements peut être géré de différentes manières. L'exemple ci-dessus utilise une fonction anonyme, mais vous pouvez également faire:
Vous pouvez affecter du code C # à une variable, le compiler au moment de l'exécution et exécuter le code:
Écrivez votre code:
// Assign C# code to the code variable.string code =@"
using System;
namespace First
{
public class Program
{
public static void Main()
{
"+"Console.WriteLine(\"Hello, world!\");"+@"
}
}
}
";
Créez le fournisseur et les paramètres du compilateur:
Réponses:
Vous pouvez l'attribuer à un
Action
comme ceci:Alors appelez-le:
Par souci d'exhaustivité (en ce qui concerne les différents commentaires) ...
Comme l'a déclaré Erik, vous pouvez exécuter plusieurs lignes de code:
Comme Tim l'a dit, vous pouvez omettre le
Action
mot - cléPour répondre au commentaire de KRyan, concernant les parenthèses vides, qui représente la liste des paramètres que vous voulez pouvoir envoyer à l'action (dans ce cas, aucun) .
Si, par exemple, que vous vouliez spécifier le message à afficher, vous pouvez ajouter « message » en tant que paramètre (notez que je l' ai changé
Action
pour afin de spécifier un seul paramètre de chaîne) :Action<string>
la source
Action ButtonClicked = () => MessageBox.Show("hi");
est équivalent et IMO plus agréable (ajoutez des parens si vous préférez)WinForms
?Button.Click
événement et ne le stocke pas dans une variable qu'il a nomméeButtonClicked
.Dans votre cas, vous souhaitez utiliser un fichier
delegate
.Voyons comment fonctionne un délégué et comment nous pouvons obtenir une forme plus simple en comprenant son concept:
Vous voyez, le délégué prend la forme d'une fonction normale mais sans aucun argument (il peut prendre n'importe quelle quantité d'arguments comme n'importe quelle autre méthode, mais pour des raisons de simplicité, ce n'est pas le cas).
Maintenant, utilisons ce que nous avons; nous définirons le délégué comme nous définissons toute autre variable:
Nous avons essentiellement 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();
Donc, tout le code serait:
À partir de là, nous pouvons passer aux expressions lambda et voir comment elles pourraient être utiles dans votre situation:
il existe de nombreux délégués déjà définis par les bibliothèques .NET, 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 définir un nouveau délégué à chaque fois. Dans le contexte précédent par exemple, vous auriez pu juste écrire
qui aurait fait de même.
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; donc, ce sont des fonctions normales mais sans nom. Ils sont de ces formes:
Dans notre cas, nous n'avons aucun paramètre donc nous utiliserons 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 à la place faire quelque chose comme ceci:
ou encore plus facile,
alors appelez simplement
ButtonClicked();
Bien sûr, vous pouvez également avoir plusieurs lignes de code, mais je ne veux pas vous embrouiller davantage. Cela ressemblerait à ceci:Vous pouvez également jouer, par exemple, vous pouvez exécuter une fonction comme celle-ci:
Désolé pour le long post, j'espère que ce n'était pas trop déroutant :)
EDIT: J'ai oublié de mentionner qu'une forme alternative qui, même si elle n'est pas souvent utilisée, pourrait rendre les expressions lambda plus faciles à comprendre:
Aussi, en utilisant des génériques:
À son tour, vous pouvez utiliser des expressions lambda, mais vous n'avez pas besoin (mais vous pourriez dans certains cas) définir le type du paramètre, par exemple, le code ci-dessus pourrait simplement être écrit comme suit:
ou:
EDIT2:
Action<string>
est une représentation depublic void delegate Action(string obj);
Action<string,string>
est une représentation depublic void delegate Action(string obj, string obj2);
En général,
Action<T>
est une représentation depublic void delegate Action<T>(T obj);
EDIT3: Je sais que le message est ici depuis un moment, mais je pense que c'est vraiment cool de ne pas le mentionner: vous pouvez le faire, ce qui est principalement lié à votre question:
ou simplement:
la source
La
Lazy
classe est spécifiquement conçue pour représenter une valeur qui ne sera pas calculée tant que vous ne l'aurez pas demandée. Vous la construisez en fournissant une méthode qui définit comment elle doit être construite, mais elle gérera l'exécution de cette méthode pas plus d'une fois (même face à plusieurs threads demandant la valeur) et renvoyant simplement la valeur déjà construite pour toute demande supplémentaire:la source
Lazy
doit être utilisé pour les valeurs qui nécessitent beaucoup de puissance de traitement, et que vous ne devez pas les utiliser pour l'interaction (car la sémantique de.Value
est qu'elle renvoie une valeur, similaire à une propriété, pas une action (interactive)). Un délégué doit être utilisé pour de telles actions à la place.Value
est utilisée; c'est leDialogResult
reçu de l'affichage de la boîte de message. La principale différence entre cette solution et l'utilisation d'un délégué est de savoir si la valeur doit être recalculée à chaque fois qu'elle est demandée ou non. Mon interprétation des exigences était que cela initialise conceptuellement une valeur, pas une opération à répéter.Lazy
peut facilement être mal utilisé. Il a une surcharge en soi, l'utiliser "juste" pour différer une petite tâche entraînera plus de surcharge qu'il n'en gagne. Afficher les boîtes de message d'une propriété est une mauvaise pratique (imo) en général, indépendamment deLazy
. Btw, de MSDN, je cite: "Utilisez l'initialisation paresseuse pour différer la création d'un objet volumineux ou gourmand en ressources" . Vous pouvez être en désaccord avec cela, mais c'est pour cela qu'il a été conçu à l'origine.Lazy
dans un contexte comme celui-ci est certainement négligeable; cela pâlira par rapport au temps passé à attendre qu'un humain clique sur une boîte de message. Cela se résume principalement aux exigences réelles de l'application sous-jacente; le caractère vague de la question rend impossible une réponse objectivement correcte. Ceci est une interprétation de la question. Quant à faire beaucoup de travail dans une propriété getter étant mauvais; apparemment, vous êtes fondamentalement opposé à la conception entière deLazy
. Vous êtes les bienvenus à cette opinion.MessageBox
la surcharge est négligeable (je n'utiliserais tout simplement pas l'interface utilisateur à l'intérieur d'une propriété). Je voulais dire de petites tâches en général (comme le report2 + 3 * 4 / i
), où la surcharge de création de la fermeture est plus grande que le calcul lui-même. Et je pense que j'adhère pleinementLazy
, en fait nous l'utilisons beaucoup en F # (un peu moins en C #) et nous avons appris à la dure qu'il faut faire attention, en particulier. dans le respect de la performance.La façon dont je lis votre question, c'est dans le contexte des contrôles GUI?
S'il s'agit de WPF, jetez un œil à la "bonne" façon de gérer les commandes des contrôles: http://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx
... mais cela peut être pénible et exagéré. Pour un cas général plus simple, vous recherchez peut-être un gestionnaire d'événements, comme:
Ce gestionnaire d'événements peut être géré de différentes manières. L'exemple ci-dessus utilise une fonction anonyme, mais vous pouvez également faire:
... comme vous le demandiez, avec une fonction (ou ici, "Action", car elle renvoie void) assignée comme variable.
la source
Vous pouvez affecter du code C # à une variable, le compiler au moment de l'exécution et exécuter le code:
Écrivez votre code:
Créez le fournisseur et les paramètres du compilateur:
Définissez les paramètres du compilateur:
Compiler l'assemblage:
Vérifier les erreurs:
Obtenez l'assembly, le type et la méthode Main:
Exécuter:
Référence:
http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime
la source