Делегат використання дій у C # [закрито]


132

Я працював з Делегатами дій у C # з надією дізнатися більше про них і подумати, де вони можуть бути корисними.

Хтось використовував Делегата дій, і якщо так, чому? чи ви можете навести кілька прикладів, де це може бути корисно?

Відповіді:


25

MSDN каже:

Цей делегат використовується методом Array.ForEach та методом List.ForEach для виконання дії над кожним елементом масиву чи списку.

Крім того, ви можете використовувати його як загальний делегат, який приймає параметри 1-3, не повертаючи жодного значення.


Я ніколи не помічав цих багатопараметричних версій Action. Дякую.
mackenir

114

Ось невеликий приклад, який показує корисність делегата 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);
    }
}

Зауважте, що метод foreach ітералізує збір імен та виконує printметод проти кожного члена колекції. Це трохи змінює парадигму для нас, розробників C #, коли ми рухаємося до більш функціонального стилю програмування. (Для отримання додаткової інформації про інформатику, що стоїть за нею, читайте це: http://en.wikipedia.org/wiki/Map_(higher-order_function) .

Тепер, якщо ви використовуєте C # 3, ви можете трохи погладшити це за допомогою лямбда-виразу:

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

Що ж, ви можете зробити одне, якщо у вас є перемикач:

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

І, маючи силу дій, ви можете перетворити цей перемикач у словник:

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

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

...

methodList[SomeEnum](someUser);

Або ви могли взяти це далі:

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

….

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

Всього пара прикладів. Звичайно, більш очевидним буде використання методів розширення Linq.


Чудово, я думаю, що це можна використати як таблицю рішень.
Бісванат

3
Ніцца - це модель рефакторингу "Замінити умовне поліморфізмом". refactoring.com/catalog/replaceConditionalWithPolymorphism.html
Девід Роббінс

16

Ви можете використовувати дії для обробників коротких подій:

btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");

Ви можете використовувати їх і для довгих; btnSubmit.Click + = (відправник, е) => {MessageBox.Show ("Ви натиснули зберегти!"); MessageBox.Show ("Ви справді зробили!"); };
tdgtyugdyugdrugdr

15

Одного разу я використав такий делегат дій у проекті:

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

що все, що він робить, - це зберігати дію (виклик методу) проти типу керування, щоб ви могли очистити всі елементи керування у формі, повернуті туди за замовчуванням.


Приємно, не велика зміна, але є щось, що називається keyedbyTypeCollection, хоча я думаю, що він обертається навколо дикторіального (тип, об'єкт).
Бісванат

13

Для прикладу того, як використовується Action <>.

Console.WriteLine має підпис, який задовольняє 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);         
    }

Сподіваюся, це допомагає


11

Я використовую його, коли я маю справу з незаконними викликами хрестових ниток, наприклад:

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

Я повинен дати кредит Reed Copsey SO користувачеві 65358 за рішення. Моє повне запитання з відповідями - це питання 2587930


3

Я використовував це як зворотний виклик в обробці подій. Коли я піднімаю подію, я передаю метод, що бере параметр string. Ось як виглядає підняття події:

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

Спосіб:

   public void UpdateMethod(string SpecialCode){ }

Оголошення класу події Args:

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

Таким чином я можу викликати метод, переданий від обробника подій, деяким параметром для оновлення даних. Я використовую це, щоб вимагати від користувача деякої інформації.


Привіт Sorskoot, ти можеш розширити, як UpdateMethod, MyEventArgs та нові BalieEventArgs грають разом. чи рядок повідомлення передається в UpdateMethod: UpdateMethod ("повідомлення")? Який метод використовує об’єкт "someDataObject"? Дякую заздалегідь
surfmuggle

2

Ми використовуємо багато функцій делегування дій у тестах. Коли нам потрібно побудувати якийсь об'єкт за замовчуванням, а пізніше потрібно його змінити. Я мало прикладу. Для побудови об'єкта за замовчуванням (John Doe) ми використовуємо BuildPerson()функцію. Пізніше ми також додаємо Джейн До, але ми змінюємо її дату народження, ім'я та висоту.

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; }
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.