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?

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.


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();
    }
}

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.


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!");

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.


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


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


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.


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; }
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.