Verwendung des Aktionsdelegierten in C # [geschlossen]

132

Ich habe mit den Aktionsdelegierten in C # zusammengearbeitet, um mehr über sie zu erfahren und zu überlegen, wo sie nützlich sein könnten.

Hat jemand den Aktionsdelegierten benutzt und wenn ja, warum? oder könnten Sie einige Beispiele nennen, wo es nützlich sein könnte?

Biswanath
quelle

Antworten:

25

MSDN sagt:

Dieser Delegat wird von der Array.ForEach-Methode und der List.ForEach-Methode verwendet, um eine Aktion für jedes Element des Arrays oder der Liste auszuführen.

Abgesehen davon können Sie es als generischen Delegaten verwenden, der 1-3 Parameter akzeptiert, ohne einen Wert zurückzugeben.

arul
quelle
Ich habe diese Multi-Parameter-Versionen von Action nie bemerkt. Vielen Dank.
Mackenir
114

Hier ist ein kleines Beispiel, das die Nützlichkeit des Aktionsdelegierten zeigt

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

Beachten Sie, dass die foreach-Methode die Sammlung von Namen iteriert und die printMethode für jedes Mitglied der Sammlung ausführt . Dies ist ein Paradigmenwechsel für uns C # -Entwickler, wenn wir uns einem funktionaleren Programmierstil zuwenden. (Weitere Informationen zur dahinter stehenden Informatik finden Sie hier: http://en.wikipedia.org/wiki/Map_(higher-order_function) .

Wenn Sie jetzt C # 3 verwenden, können Sie dies mit einem Lambda-Ausdruck wie folgt etwas verbessern:

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
quelle
68

Eine Sache, die Sie tun können, ist, wenn Sie einen Schalter haben:

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

Und mit der Macht der Aktionen können Sie diesen Schalter in ein Wörterbuch verwandeln:

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

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

...

methodList[SomeEnum](someUser);

Oder Sie könnten weiter gehen:

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

....

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

Nur ein paar Beispiele. Die offensichtlichere Verwendung wären natürlich Linq-Erweiterungsmethoden.

Programmierwerkzeug
quelle
Großartig, ich denke, dies könnte als Entscheidungstabelle verwendet werden.
Biswanath
3
Schön - dies ist ein Refactoring-Muster "Bedingte durch Polymorphismus ersetzen". refactoring.com/catalog/replaceConditionalWithPolymorphism.html
David Robbins
16

Sie können Aktionen für kurze Ereignishandler verwenden:

btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
Aaron Powell
quelle
Sie können sie auch für lange verwenden; btnSubmit.Click + = (Absender, e) => {MessageBox.Show ("Sie haben auf Speichern geklickt!"); MessageBox.Show ("Das hast du wirklich getan!"); };
tdgtyugdyugdrugdr
15

Ich habe den Aktionsdelegierten einmal in einem Projekt verwendet:

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

Sie speichern lediglich eine Aktion (Methodenaufruf) für einen Steuerelementtyp, damit Sie alle Steuerelemente in einem Formular auf die Standardeinstellungen zurücksetzen können.

Nathan W.
quelle
Schön, keine große Veränderung, aber es gibt etwas namens keyedbyTypeCollection, obwohl ich denke, dass es sich um ein Diktat (Typ, Objekt) handelt.
Biswanath
13

Ein Beispiel für die Verwendung von Aktion <>.

Console.WriteLine hat eine Signatur, die zufriedenstellend ist 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);         
    }

Hoffe das hilft

Binärer Worrier
quelle
11

Ich benutze es, wenn ich mit illegalen Cross-Thread-Anrufen zu tun habe. Zum Beispiel:

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

Ich muss Reed Copsey SO Benutzer 65358 für die Lösung gutschreiben. Meine vollständige Frage mit Antworten ist SO Frage 2587930

Ron Skufca
quelle
3

Ich habe es als Rückruf in einem Event-Handler verwendet. Wenn ich das Ereignis auslöse, übergebe ich eine Methode, die einen String als Parameter verwendet. So sieht die Auslösung der Veranstaltung aus:

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

Die Methode:

   public void UpdateMethod(string SpecialCode){ }

Das ist die Klassendeklaration des Ereignisses Args:

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

Auf diese Weise kann ich die vom Ereignishandler übergebene Methode mit einem Parameter aufrufen, um die Daten zu aktualisieren. Ich benutze dies, um einige Informationen vom Benutzer anzufordern.

Sorskoot
quelle
Hallo Sorskoot, könnten Sie erweitern, wie UpdateMethod, MyEventArgs und neue BalieEventArgs zusammen spielen? Wird die Zeichenfolge Nachricht an UpdateMethod: UpdateMethod ("Eine Nachricht") übergeben? Welche Methode verwendet das Objekt "someDataObject"? Vielen Dank im Voraus
Surfmuggle
2

In Tests verwenden wir viele Funktionen für Aktionsdelegierte. Wenn wir ein Standardobjekt erstellen und später ändern müssen. Ich habe ein kleines Beispiel gemacht. Um ein Standardobjekt für eine Person (John Doe) zu erstellen, verwenden wir die BuildPerson()Funktion. Später fügen wir auch Jane Doe hinzu, aber wir ändern ihr Geburtsdatum sowie ihren Namen und ihre Größe.

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; }
    }
der Böse
quelle