Pracowałem z delegatami akcji w języku C # w nadziei, że dowiem się o nich więcej i pomyśleć, gdzie mogą być przydatne.
Czy ktoś użył delegata akcji, a jeśli tak, to dlaczego? czy możesz podać kilka przykładów, w których może to być przydatne?
MSDN mówi:
Ten delegat jest używany przez metodę Array.ForEach i metodę List.ForEach do wykonywania akcji na każdym elemencie tablicy lub listy.
Poza tym można go używać jako delegata ogólnego, który przyjmuje 1-3 parametry bez zwracania żadnej wartości.
Oto mały przykład, który pokazuje przydatność delegata akcji
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); } }
Zwróć uwagę, że metoda foreach iteruje kolekcję nazw i wykonuje
print
metodę dla każdego elementu członkowskiego kolekcji. To trochę zmiana paradygmatu dla nas, programistów C #, w miarę zbliżania się do bardziej funkcjonalnego stylu programowania. (Aby uzyskać więcej informacji na temat informatyki, która się za tym kryje, przeczytaj to: http://en.wikipedia.org/wiki/Map_(higher-order_function) .Teraz, jeśli używasz C # 3, możesz nieco poprawić to za pomocą wyrażenia lambda, takiego jak:
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(); } }
źródło
Cóż, jedna rzecz, którą możesz zrobić, to jeśli masz przełącznik:
switch(SomeEnum) { case SomeEnum.One: DoThings(someUser); break; case SomeEnum.Two: DoSomethingElse(someUser); break; }
Dzięki potędze działań możesz zmienić ten przełącznik w słownik:
Dictionary<SomeEnum, Action<User>> methodList = new Dictionary<SomeEnum, Action<User>>() methodList.Add(SomeEnum.One, DoSomething); methodList.Add(SomeEnum.Two, DoSomethingElse);
...
Lub możesz pójść dalej:
....
var neededMethod = methodList[SomeEnum]; SomeOtherMethod(neededMethod, someUser);
Tylko kilka przykładów. Oczywiście bardziej oczywistym zastosowaniem byłyby metody rozszerzeń Linq.
źródło
Możesz użyć akcji dla krótkich programów obsługi zdarzeń:
btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
źródło
Kiedyś użyłem delegata akcji w taki sposób w projekcie:
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()} };
jedyne, co robi, to zapisywanie akcji (wywołanie metody) w odniesieniu do typu kontrolki, dzięki czemu można wyczyścić wszystkie kontrolki w formularzu z powrotem do wartości domyślnych.
źródło
Jako przykład użycia Action <>.
Console.WriteLine ma podpis, który jest satysfakcjonujący
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); }
Mam nadzieję że to pomoże
źródło
Używam go, gdy mam do czynienia z nielegalnymi połączeniami między wątkami Na przykład:
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(); }));
Muszę przyznać uznanie użytkownikowi Reed Copsey SO 65358 za rozwiązanie. Moje pełne pytanie z odpowiedziami to pytanie SO 2587930
źródło
Użyłem go jako wywołania zwrotnego w programie obsługi zdarzeń. Kiedy podnoszę zdarzenie, przekazuję metodę pobierającą ciąg jako parametr. Oto jak wygląda podbicie wydarzenia:
SpecialRequest(this, new BalieEventArgs { Message = "A Message", Action = UpdateMethod, Data = someDataObject });
Metoda:
public void UpdateMethod(string SpecialCode){ }
Jest to deklaracja klasy zdarzenia Args:
public class MyEventArgs : EventArgs { public string Message; public object Data; public Action<String> Action; }
W ten sposób mogę wywołać metodę przekazaną z programu obsługi zdarzeń z pewnym parametrem, aby zaktualizować dane. Używam tego, aby poprosić użytkownika o pewne informacje.
źródło
W testach używamy wielu funkcji delegowania akcji. Kiedy musimy zbudować jakiś domyślny obiekt, a później musimy go zmodyfikować. Zrobiłem mały przykład. Aby zbudować domyślny obiekt osoby (John Doe), używamy
BuildPerson()
funkcji. Później dodajemy też Jane Doe, ale modyfikujemy jej datę urodzenia, imię i wzrost.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; } }
źródło