Usos de la Acción delegar en C#


Estaba trabajando con los Delegados de Acción en C# con la esperanza de aprender más sobre ellos y pensar dónde podrían ser útiles.

¿Alguien ha usado el Delegado de Acción, y si es así, por qué? ¿o podría dar algunos ejemplos donde podría ser útil?

Author: Mikael Engver, 2008-12-16

9 answers

MSDN dice:

Este delegado es utilizado por el Matriz.Método ForEach y el Lista.ForEach método para realizar un acción sobre cada elemento de la matriz o lista.

Excepto que, puede usarlo como un delegado genérico que toma 1-3 parámetros sin devolver ningún valor.

 25
Author: arul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 11:46:16

Aquí hay un pequeño ejemplo que muestra la utilidad de la Acción delegate

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 el método foreach itera la colección de nombres y ejecuta el método print contra cada miembro de la colección. Este es un cambio de paradigma para nosotros los desarrolladores de C # a medida que avanzamos hacia un estilo de programación más funcional. (Para obtener más información sobre la informática detrás de él, lea esto: http://en.wikipedia.org/wiki/Map_ (higher-order_function).

Ahora si eres usando C # 3 puedes pulir esto un poco con una expresión lambda como esta:

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();
    }
}
 113
Author: Andrew Hare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-08 21:47:08

Bueno, una cosa que podrías hacer es si tienes un interruptor:

switch(SomeEnum)
{
  case SomeEnum.One:
      DoThings(someUser);
      break;
  case SomeEnum.Two:
      DoSomethingElse(someUser);
      break;
}

Y con el poder de las acciones puedes convertir ese interruptor en un diccionario:

Dictionary<SomeEnum, Action<User>> methodList = 
    new Dictionary<SomeEnum, Action<User>>()

methodList.Add(SomeEnum.One, DoSomething);
methodList.Add(SomeEnum.Two, DoSomethingElse); 

...

methodList[SomeEnum](someUser);

O podrías llevar esto más lejos:

SomeOtherMethod(Action<User> someMethodToUse, User someUser)
{
    someMethodToUse(someUser);
}  

....

var neededMethod = methodList[SomeEnum];
SomeOtherMethod(neededMethod, someUser);

Solo un par de ejemplos. Por supuesto, el uso más obvio serían los métodos de extensión Linq.

 67
Author: Programmin Tool,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-02 17:59:39

Puedes usar acciones para manejadores de eventos cortos:

btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
 16
Author: Aaron Powell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 12:07:47

Usé la acción delegate como esta en un proyecto una 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()}
    };

Que todo lo que hace es almacenar una acción(llamada al método) contra un tipo de control para que pueda borrar todos los controles de un formulario de vuelta a sus valores predeterminados.

 14
Author: Nathan W,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 11:53:02

Para un ejemplo de cómo se usa Action.

Consola.WriteLine tiene una firma que satisifica 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 esto ayude

 13
Author: Binary Worrier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 12:02:21

Lo uso cuando estoy tratando con Llamadas Ilegales de Hilos Cruzados, Por ejemplo:

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

Debo dar crédito a Reed Copsey SO usuario 65358 para la solución. Mi pregunta completa con respuestas es SO Question 2587930

 11
Author: Ron Skufca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:29

Lo usé como devolución de llamada en un controlador de eventos. Cuando subo el evento, paso un método tomando una cadena como parámetro. Así es como se ve la elevación del evento:

SpecialRequest(this,
    new BalieEventArgs 
    { 
            Message = "A Message", 
            Action = UpdateMethod, 
            Data = someDataObject 
    });

El Método:

   public void UpdateMethod(string SpecialCode){ }

La es la declaración de clase del evento Args:

public class MyEventArgs : EventArgs
    {
        public string Message;
        public object Data;
        public Action<String> Action;
    }

De esta manera puedo llamar al método pasado desde el controlador de eventos con un parámetro some para actualizar los datos. Utilizo esto para solicitar información al usuario.

 3
Author: Sorskoot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-16 11:51:08

Usamos mucha funcionalidad de delegado de acciones en las pruebas. Cuando necesitamos construir algún objeto predeterminado y luego necesitamos modificarlo. Hice un pequeño ejemplo. Para construir el objeto persona por defecto (John Doe) usamos la función BuildPerson(). Más tarde añadimos Jane Doe también, pero modificamos su fecha de nacimiento y nombre y 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; }
    }
 1
Author: evilone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-09 14:50:28