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?

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.


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();
    }
}

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.


Ó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!");

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.


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


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


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.


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; }
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.