Использование делегата действия в С#
Я работал с делегатами Action на С# в надежде узнать больше о них и подумать, где они могут быть полезны.
Кто-нибудь использовал делегата действий, и если да, то почему? или вы могли бы привести несколько примеров, где это может быть полезно?
Ответы
Ответ 1
MSDN говорит:
Этот делегат используется Метод Array.ForEach и List.ForEach для выполнения действие для каждого элемента массива или список.
Кроме того, вы можете использовать его как общий делегат, который принимает 1-3 параметра, не возвращая никакого значения.
Ответ 2
Вот небольшой пример, показывающий полезность делегата 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
по отношению к каждому члену коллекции. Это немного смещение парадигмы для разработчиков С#, когда мы продвигаемся к более функциональному стилю программирования. (Для получения дополнительной информации об информатике за ней прочтите следующее: http://en.wikipedia.org/wiki/Map_ (high-order_function).
Теперь, если вы используете С# 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();
}
}
Ответ 3
Ну, одна вещь, которую вы могли бы сделать, это если у вас есть переключатель:
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.
Ответ 4
Вы можете использовать действия для коротких обработчиков событий:
btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
Ответ 5
Я использовал делегат действия, как это, в проекте один раз:
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()}
};
что все, что он делает, это сохранить действие (вызов метода) против типа элемента управления, чтобы вы могли очистить все элементы управления формы до того, как они по умолчанию установлены.
Ответ 6
Пример использования 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);
}
Надеюсь, что это поможет
Ответ 7
Я использую его, когда имею дело с вызовами нелегального перекрестного потока Например:
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
Ответ 8
Я использовал его как обратный вызов в обработчике событий. Когда я поднимаю событие, я передаю метод, беря строку за параметр. Вот как выглядит событие:
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;
}
Таким образом, я могу вызвать метод, переданный из обработчика события, с некоторым параметром для обновления данных. Я использую это для запроса некоторой информации от пользователя.
Ответ 9
В тестах мы используем много функций делегата Action. Когда нам нужно создать какой-то объект по умолчанию, а затем нужно его изменить. Я сделал небольшой пример. Для создания объекта по умолчанию (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; }
}