Utilisations du délégué Action en C # [fermé]

132

Je travaillais avec les délégués à l'action en C # dans l'espoir d'en apprendre davantage sur eux et de réfléchir aux domaines où ils pourraient être utiles.

Quelqu'un a-t-il utilisé le délégué d'action, et si oui, pourquoi? ou pourriez-vous donner des exemples où cela pourrait être utile?

Biswanath
la source

Réponses:

25

MSDN dit:

Ce délégué est utilisé par la méthode Array.ForEach et la méthode List.ForEach pour effectuer une action sur chaque élément du tableau ou de la liste.

Sauf que, vous pouvez l'utiliser comme un délégué générique qui prend 1 à 3 paramètres sans renvoyer de valeur.

arul
la source
Je n'ai jamais remarqué ces versions multi-paramètres d'Action. Merci.
mackenir
114

Voici un petit exemple qui montre l'utilité du délégué Action

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Action<String> print = new Action<String>(Program.Print);

        List<String> names = new List<String> { "andrew", "nicole" };

        names.ForEach(print);

        Console.Read();
    }

    static void Print(String s)
    {
        Console.WriteLine(s);
    }
}

Notez que la méthode foreach itère la collection de noms et exécute la printméthode sur chaque membre de la collection. C'est un peu un changement de paradigme pour nous, développeurs C #, alors que nous nous dirigeons vers un style de programmation plus fonctionnel. (Pour plus d'informations sur l'informatique derrière cela, lisez ceci: http://en.wikipedia.org/wiki/Map_(higher-order_function) .

Maintenant, si vous utilisez C # 3, vous pouvez lisser un peu cela avec une expression lambda comme ceci:

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<String> names = new List<String> { "andrew", "nicole" };

        names.ForEach(s => Console.WriteLine(s));

        Console.Read();
    }
}
Andrew Hare
la source
68

Eh bien, une chose que vous pourriez faire est si vous avez un commutateur:

switch(SomeEnum)
{
  case SomeEnum.One:
      DoThings(someUser);
      break;
  case SomeEnum.Two:
      DoSomethingElse(someUser);
      break;
}

Et avec la puissance des actions, vous pouvez transformer ce commutateur en dictionnaire:

Dictionary<SomeEnum, Action<User>> methodList = 
    new Dictionary<SomeEnum, Action<User>>()

methodList.Add(SomeEnum.One, DoSomething);
methodList.Add(SomeEnum.Two, DoSomethingElse); 

...

methodList[SomeEnum](someUser);

Ou vous pouvez aller plus loin:

SomeOtherMethod(Action<User> someMethodToUse, User someUser)
{
    someMethodToUse(someUser);
}  

....

var neededMethod = methodList[SomeEnum];
SomeOtherMethod(neededMethod, someUser);

Juste quelques exemples. Bien sûr, l'utilisation la plus évidente serait les méthodes d'extension Linq.

Outil Programmin
la source
Super, je pense que cela pourrait être utilisé comme table de décision.
Biswanath
3
Nice - c'est un modèle de refactoring "Remplacer le conditionnel par le polymorphisme". refactoring.com/catalog/replaceConditionalWithPolymorphism.html
David Robbins
16

Vous pouvez utiliser des actions pour les gestionnaires d'événements courts:

btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
Aaron Powell
la source
Vous pouvez également les utiliser pour les longs; btnSubmit.Click + = (expéditeur, e) => {MessageBox.Show ("Vous avez cliqué sur Enregistrer!"); MessageBox.Show ("Vous l'avez vraiment fait!"); };
tdgtyugdyugdrugdr
15

J'ai utilisé le délégué d'action comme celui-ci dans un projet une fois:

private static Dictionary<Type, Action<Control>> controldefaults = new Dictionary<Type, Action<Control>>() { 
            {typeof(TextBox), c => ((TextBox)c).Clear()},
            {typeof(CheckBox), c => ((CheckBox)c).Checked = false},
            {typeof(ListBox), c => ((ListBox)c).Items.Clear()},
            {typeof(RadioButton), c => ((RadioButton)c).Checked = false},
            {typeof(GroupBox), c => ((GroupBox)c).Controls.ClearControls()},
            {typeof(Panel), c => ((Panel)c).Controls.ClearControls()}
    };

tout ce qu'il fait est de stocker une action (appel de méthode) sur un type de contrôle afin que vous puissiez effacer tous les contrôles d'un formulaire à leurs valeurs par défaut.

Nathan W
la source
Bien, pas beaucoup de changement mais il y a quelque chose qui s'appelle keyedbyTypeCollection, bien que je pense que cela englobe le dictioinary (type, Object), peut-être.
Biswanath
13

Pour un exemple de la façon dont Action <> est utilisée.

Console.WriteLine a une signature qui satisfait Action<string>.

    static void Main(string[] args)
    {
        string[] words = "This is as easy as it looks".Split(' ');

        // Passing WriteLine as the action
        Array.ForEach(words, Console.WriteLine);         
    }

J'espère que cela t'aides

Binaire Worrier
la source
11

Je l'utilise lorsque je traite des appels croisés illégaux.Par exemple:

DataRow dr = GetRow();
this.Invoke(new Action(() => {
   txtFname.Text = dr["Fname"].ToString();
   txtLname.Text = dr["Lname"].ToString(); 
   txtMI.Text = dr["MI"].ToString();
   txtSSN.Text = dr["SSN"].ToString();
   txtSSN.ButtonsRight["OpenDialog"].Visible = true;
   txtSSN.ButtonsRight["ListSSN"].Visible = true;
   txtSSN.Focus();
}));

Je dois remercier l'utilisateur Reed Copsey SO 65358 pour la solution. Ma question complète avec réponses est SO Question 2587930

Ron Skufca
la source
3

Je l'ai utilisé comme rappel dans un gestionnaire d'événements. Quand je déclenche l'événement, je passe une méthode prenant une chaîne comme paramètre. Voici à quoi ressemble la remontée de l'événement:

SpecialRequest(this,
    new BalieEventArgs 
    { 
            Message = "A Message", 
            Action = UpdateMethod, 
            Data = someDataObject 
    });

La méthode:

   public void UpdateMethod(string SpecialCode){ }

La est la déclaration de classe de l'événement Args:

public class MyEventArgs : EventArgs
    {
        public string Message;
        public object Data;
        public Action<String> Action;
    }

De cette façon, je peux appeler la méthode transmise par le gestionnaire d'événements avec un paramètre pour mettre à jour les données. J'utilise ceci pour demander des informations à l'utilisateur.

Sorskoot
la source
Salut Sorskoot, pourriez-vous expliquer comment UpdateMethod, MyEventArgs et les nouveaux BalieEventArgs jouent ensemble. la chaîne Message est-elle passée dans UpdateMethod: UpdateMethod ("A Message")? Quelle méthode utilise l'objet "someDataObject"? Merci d'avance
Surfmuggle
2

Nous utilisons beaucoup de fonctionnalités de délégué d'action dans les tests. Lorsque nous avons besoin de construire un objet par défaut et que nous devons ensuite le modifier. J'ai fait un petit exemple. Pour créer l'objet personne par défaut (John Doe), nous utilisons la BuildPerson()fonction. Plus tard, nous ajoutons aussi Jane Doe, mais nous modifions sa date de naissance, son nom et sa taille.

public class Program
{
        public static void Main(string[] args)
        {
            var person1 = BuildPerson();

            Console.WriteLine(person1.Firstname);
            Console.WriteLine(person1.Lastname);
            Console.WriteLine(person1.BirthDate);
            Console.WriteLine(person1.Height);

            var person2 = BuildPerson(p =>
            {
                p.Firstname = "Jane";
                p.BirthDate = DateTime.Today;
                p.Height = 1.76;
            });

            Console.WriteLine(person2.Firstname);
            Console.WriteLine(person2.Lastname);
            Console.WriteLine(person2.BirthDate);
            Console.WriteLine(person2.Height);

            Console.Read();
        }

        public static Person BuildPerson(Action<Person> overrideAction = null)
        {
            var person = new Person()
            {
                Firstname = "John",
                Lastname = "Doe",
                BirthDate = new DateTime(2012, 2, 2)
            };

            if (overrideAction != null)
                overrideAction(person);

            return person;
        }
    }

    public class Person
    {
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public DateTime BirthDate { get; set; }
        public double Height { get; set; }
    }
maléfique
la source