Delegado de usos da ação em C # [fechado]

132

Eu estava trabalhando com os Delegados de Ação em C # na esperança de aprender mais sobre eles e pensar onde eles poderiam ser úteis.

Alguém já usou o Delegado de Ação e, em caso afirmativo, por quê? ou você pode dar alguns exemplos onde isso pode ser útil?

Biswanath
fonte

Respostas:

25

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.

arul
fonte
Eu nunca notei aquelas versões com vários parâmetros do Action. Obrigado.
1026868
114

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 printmé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();
    }
}
Andrew Hare
fonte
68

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.

Ferramenta Programmin
fonte
Ótimo, acho que isso poderia ser usado como uma tabela de decisão.
Biswanath
3
Bom - esse é um padrão de refatoração "Substituir condicional pelo polimorfismo". refactoring.com/catalog/replaceConditionalWithPolymorphism.html
David Robbins
16

Você pode usar ações para manipuladores de eventos curtos:

btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
Aaron Powell
fonte
Você também pode usá-los por longos; btnSubmit.Click + = (remetente, e) => {MessageBox.Show ("Você clicou em salvar!"); MessageBox.Show ("Você realmente fez!"); };
tdgtyugdyugdrugdr
15

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.

Nathan W
fonte
Bom, não há muita mudança, mas há algo chamado keyedbyTypeCollection, embora eu ache que isso envolve o dictioinary (tipo, Object), pode ser.
Biswanath 16/12/08
13

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

Preocupação binária
fonte
11

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

Ron Skufca
fonte
3

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.

Sorskoot
fonte
Olá Sorskoot, você poderia expandir como o UpdateMethod, o MyEventArgs e o novo BalieEventArgs estão tocando juntos. é a cadeia de caracteres Message passada para UpdateMethod: UpdateMethod ("A Message")? Qual método usa o objeto "someDataObject"? Agradecemos antecipadamente
surfmuggle
2

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