Использование делегата действия в C#

Я работал с делегатами действий на C# в надежде узнать о них больше и подумать, где они могут быть полезны.

Кто-нибудь использовал Action Delegate, и если да, то почему? или вы могли бы привести несколько примеров, где это могло бы быть полезно?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
133
0
122 267
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Ответ принят как подходящий

MSDN говорит:

This delegate is used by the Array.ForEach method and the List.ForEach method to perform an action on each element of the array or list.

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

Я никогда не замечал этих многопараметрических версий Action. Спасибо.

mackenir 16.12.2008 15:07

Я использовал его как обратный вызов в обработчике событий. Когда я вызываю событие, я передаю метод, принимающий строку в качестве параметра. Вот как выглядит постановка ивента:

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

Таким образом, я могу вызвать метод, переданный из обработчика событий, с некоторым параметром для обновления данных. Я использую это, чтобы запросить у пользователя некоторую информацию.

Привет, Сорскут, не могли бы вы рассказать, как UpdateMethod, MyEventArgs и новый BalieEventArgs работают вместе. Строка Message передана в UpdateMethod: UpdateMethod («Сообщение»)? Какой метод использует объект someDataObject? заранее спасибо

surfmuggle 04.06.2013 22:16

Я однажды использовал такой делегат действия в проекте:

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, хотя я думаю, что это может быть связано с dictioinary (type, Object).

Biswanath 16.12.2008 15:21

Что ж, одну вещь вы могли бы сделать, если у вас есть переключатель:

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.

Отлично, я думаю, это можно было бы использовать как таблицу решений.

Biswanath 16.12.2008 15:22

Красиво - это шаблон рефакторинга «Замени условного на полиморфизм». refactoring.com/catalog/replaceConditionalWithPolymorphism.h‌ tml

David Robbins 18.10.2009 23:39

Пример использования 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);         
    }

Надеюсь это поможет

Вы можете использовать действия для коротких обработчиков событий:

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

Вы можете использовать их и для длинных; btnSubmit.Click + = (sender, e) => {MessageBox.Show («Вы нажали кнопку« Сохранить »!»); MessageBox.Show («Вы действительно сделали!»); };

tdgtyugdyugdrugdr 24.08.2015 17:23

Вот небольшой пример, демонстрирующий полезность делегата действия.

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

Я использую его, когда имею дело с незаконными вызовами перекрестных потоков. Например:

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 за решение. Мой полный вопрос с ответами: SO Вопрос 2587930

В тестах мы используем множество функций делегирования действий. Когда нам нужно создать какой-то объект по умолчанию, а позже нужно его изменить. Я привел небольшой пример. Для создания объекта «человек по умолчанию» (Джон Доу) мы используем функцию 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; }
    }

Другие вопросы по теме