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