Respostas:
MSDN diz:
Esse delegado é usado pelo método Array.ForEach e pelo método List.ForEach para executar uma ação em cada elemento da matriz ou lista.
Exceto que, você pode usá-lo como um representante genérico que usa 1-3 parâmetros sem retornar nenhum valor.
Aqui está um pequeno exemplo que mostra a utilidade do delegado 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);
}
}
Observe que o método foreach itera a coleção de nomes e executa o print
método em cada membro da coleção. Essa é uma mudança de paradigma para os desenvolvedores de C # à medida que avançamos em direção a um estilo de programação mais funcional. (Para obter mais informações sobre a ciência da computação por trás, leia isto: http://en.wikipedia.org/wiki/Map_(higher-order_function) .
Agora, se você estiver usando o C # 3, você pode usar um pouco disso com uma expressão lambda da seguinte maneira:
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();
}
}
Bem, uma coisa que você pode fazer é se você tiver uma opção:
switch(SomeEnum)
{
case SomeEnum.One:
DoThings(someUser);
break;
case SomeEnum.Two:
DoSomethingElse(someUser);
break;
}
E com o poder das ações, você pode transformar essa chave em um dicionário:
Dictionary<SomeEnum, Action<User>> methodList =
new Dictionary<SomeEnum, Action<User>>()
methodList.Add(SomeEnum.One, DoSomething);
methodList.Add(SomeEnum.Two, DoSomethingElse);
...
methodList[SomeEnum](someUser);
Ou você pode levar isso mais longe:
SomeOtherMethod(Action<User> someMethodToUse, User someUser)
{
someMethodToUse(someUser);
}
....
var neededMethod = methodList[SomeEnum];
SomeOtherMethod(neededMethod, someUser);
Apenas alguns exemplos. Obviamente, o uso mais óbvio seria os métodos de extensão Linq.
Você pode usar ações para manipuladores de eventos curtos:
btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
Eu usei o delegado de ação como este em um projeto uma vez:
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()}
};
tudo o que faz é armazenar uma ação (chamada de método) em um tipo de controle, para que você possa limpar todos os controles de um formulário para os padrões anteriores.
Para um exemplo de como a ação <> é usada.
Console.WriteLine tem uma assinatura que satisfaz 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);
}
Espero que isto ajude
Eu o uso quando estou lidando com chamadas de linha cruzada ilegal. Por exemplo:
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();
}));
Devo dar crédito ao usuário 65358 da Reed Copsey SO pela solução. Minha pergunta completa com respostas é SO Pergunta 2587930
Usei-o como retorno de chamada em um manipulador de eventos. Quando eu levanto o evento, passo um método usando uma string como parâmetro. É assim que o evento é apresentado:
SpecialRequest(this,
new BalieEventArgs
{
Message = "A Message",
Action = UpdateMethod,
Data = someDataObject
});
O método:
public void UpdateMethod(string SpecialCode){ }
A é a declaração de classe do evento Args:
public class MyEventArgs : EventArgs
{
public string Message;
public object Data;
public Action<String> Action;
}
Dessa forma, eu posso chamar o método passado do manipulador de eventos com um parâmetro para atualizar os dados. Eu uso isso para solicitar algumas informações do usuário.
Usamos muitas funcionalidades de delegação de ação nos testes. Quando precisamos construir algum objeto padrão e depois modificá-lo. Eu fiz pouco exemplo. Para construir o objeto de pessoa padrão (John Doe), usamos a BuildPerson()
função Mais tarde, adicionamos Jane Doe também, mas modificamos sua data de nascimento, nome e altura.
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; }
}