




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 параметра без возврата какого-либо значения.
Я использовал его как обратный вызов в обработчике событий. Когда я вызываю событие, я передаю метод, принимающий строку в качестве параметра. Вот как выглядит постановка ивента:
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? заранее спасибо
Я однажды использовал такой делегат действия в проекте:
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).
Что ж, одну вещь вы могли бы сделать, если у вас есть переключатель:
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.
Отлично, я думаю, это можно было бы использовать как таблицу решений.
Красиво - это шаблон рефакторинга «Замени условного на полиморфизм». refactoring.com/catalog/replaceConditionalWithPolymorphism.h tml
Пример использования 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 («Вы действительно сделали!»); };
Вот небольшой пример, демонстрирующий полезность делегата действия.
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; }
}
Я никогда не замечал этих многопараметрических версий Action. Спасибо.