Uso en el mundo real de los delegados de C # [cerrado]

14

Creo que entiendo conceptualmente a los delegados de C #, sin embargo, estoy luchando por encontrar un ejemplo del mundo real en el que puedan ser útiles. ¿Puede proporcionar algunas respuestas que detallan cómo se utilizaron los delegados de C # en aplicaciones reales y qué problemas le permitieron moverse?

    
pregunta AlexC 28.02.2011 - 21:54
fuente

10 respuestas

15

El código de la GUI utiliza delegados para manejar eventos, como los clics en los botones y los movimientos de ventanas. El uso del delegado le permite tener una función llamada siempre que ocurra el evento. Un ejemplo sería vincular una función que guarda datos en un botón "Guardar" en la interfaz. Cuando se hace clic en el botón, se configura para ejecutar la función que guarda los datos. Es útil en la programación de GUI porque su programa completo podría estar esperando que el usuario haga algo y no tiene forma de saber qué hará primero. El uso de delegados permite que la funcionalidad de su programa se conecte a la interfaz de usuario de manera que el usuario pueda hacer las cosas de la manera que desee.

    
respondido por el FrustratedWithFormsDesigner 28.02.2011 - 21:58
fuente
12

Prácticamente cualquier cosa que use el Patrón del observador probablemente implementará delegados.

Lea la descripción y probablemente imaginará algunos escenarios en los que los usaría. El manejo de eventos GUI es un ejemplo común.

    
respondido por el whatsisname 28.02.2011 - 22:05
fuente
11

Linq usa los delegados Func<T> y Action<T> en todo el lugar como parámetros.

Esto le permite usar expresiones lambda como parámetros y definir la acción que se realizará como parte de la lista de parámetros.

    
respondido por el Oded 28.02.2011 - 22:04
fuente
9

Los delegados son muy útiles en la programación asíncrona.

Tienes una clase que hace cosas de forma asíncrona y tiene una devolución de llamada. Puede invocar el método de delegado al devolver la llamada, y la implementación de su clase aplicará la lógica descrita en su método de delegado.     

respondido por el James Love 28.02.2011 - 22:11
fuente
9

Los delegados son particularmente útiles como una solución para el agujero en el patrón medio . Esencialmente, hay muchos casos en los que desea envolver un conjunto único de instrucciones dentro de un conjunto común de instrucciones. Es particularmente difícil si las instrucciones antes y después del bit único necesitan compartir el estado. Con los delegados, puede pasar un delegado a una función. La función ejecuta el bit anterior, ejecuta el delegado, luego ejecuta el bit posterior.

    
respondido por el Scott Whitlock 28.02.2011 - 22:30
fuente
5

En los "viejos tiempos" de lenguajes que no eran OOP como Fortran y C, era increíblemente útil poder tener una subrutina para recibir un argumento que era un indicador de una función. Por ejemplo, la función qsort funciona con una función de comparación proporcionada por el usuario. Existen numerosas subrutinas para resolver ecuaciones diferenciales ordinarias o para optimizar funciones, y todas ellas toman los punteros de función como argumentos.

En los sistemas de ventanas, todos los tipos de devoluciones de llamada siguen el mismo patrón.

En Lisp, incluso en los primeros días, había algo llamado "argumento funcional" o FUNARG, que no solo era una función, sino que también contenía un contexto de almacenamiento donde podía recordar e interactuar con una parte del mundo exterior. .

Esta misma necesidad existe en lenguajes OOP, excepto cuando pasa la dirección de una función, también tiene que pasar la dirección del objeto del que la función es un método. Eso es dos cosas que tienes que pasar. Así que un delegado es solo eso, y permite que se siga utilizando ese buen patrón antiguo.

    
respondido por el Mike Dunlavey 28.02.2011 - 22:48
fuente
3

Este es un ejemplo simple que muestra cuán útiles pueden ser los delegados para crear un código simple que siga el principio DRY. También le permite mantener el código muy cerca de donde se necesita.

Action<Button, Action<Button>> prepareButton = 
    (btn, nxt) => { 
        btn.Height = 32;
        btn.Width= 64;
        nxt(btn);
    };

prepareButton(myBtn1, btn => btn.Text = "A");
prepareButton(myBtn2, btn => btn.Text = "B");
prepareButton(myBtn3, btn => btn.Text = "C");

Este es un ejemplo real de la ventaja que proporcionan los delegados.

protected override void PageInitialize()
{
    const string selectCodeFormat = "javascript:selectCode('{0}', '{1}');";
    const string onClick = "return toggleElement(this);";

    Func<HtmlGenericControl> getElement = null;
    Action<HtmlGenericControl> setElement = null, addChild = null;
    HtmlGenericControl level1Element = null, level2Element = null, level3Element = null, level4Element = null;
    string className = null, code = null, description = null;           

    using (var records = Core.Database.ExecuteRecords("code.SocCodeTree"))
    {
        while (records.Read())
        {
            code = records.GetString("Code");
            description = records.GetString("Description"); 

            if (records.GetString("Level4") != "")
            {
                className = "Level4";
                setElement = e => level4Element = e;
                getElement = () => level4Element;
                addChild = e => level3Element.Controls.Add(e);
            }
            else if (records.GetString("Level3") != "")
            {
                className = "Level3";
                setElement = e => level3Element = e;
                getElement = () => level3Element;
                addChild = e => level2Element.Controls.Add(e);
            }
            else if (records.GetString("Level2") != "")
            {
                className = "Level2";
                setElement = e => level2Element = e;
                getElement = () => level2Element;
                addChild = e => level1Element.Controls.Add(e);
            }
            else
            {
                className = "Level1";
                setElement = e => level1Element = e;
                getElement = () => level1Element;
                addChild = e => Root.Controls.Add(e);
            }

            var child = new HtmlGenericControl("li");
            child.Attributes["class"] = className;
            var span = new HtmlGenericControl("span") { 
                InnerText = code + " - " + description + " - " 
            };
            span.Attributes["onclick"] = onClick;
            child.Controls.Add(span);
            var a = new HtmlAnchor() { 
                InnerText = "Select", 
                HRef = string.Format(selectCodeFormat, code, description) 
            };
            child.Controls.Add(a);
            setElement(new HtmlGenericControl("ul"));
            child.Controls.Add(getElement());
            addChild(child);    
        }
    }
}
    
respondido por el ChaosPandion 28.02.2011 - 22:14
fuente
2

Mi primer encuentro con delegados fue buscar una actualización del programa (Windows Forms C # 3.5) descargando un archivo de mi sitio web, pero para evitar la verificación de la actualización bloqueando todo el programa, usé un delegado y un hilo para hacerlo de forma asincrónica.

    
respondido por el Kenneth Posey 01.03.2011 - 00:37
fuente
1

He visto implementaciones interesantes del patrón de Estrategia que utiliza delegados de manera efectiva. (es decir, la estrategia es un delegado)

El que estaba buscando era para la búsqueda de rutas donde el algoritmo para encontrar la ruta era un delegado al que se podía (re) asignar en tiempo de ejecución para que pudieran usarse diferentes algoritmos (BFS vs A * etc.)

    
respondido por el Steven Evers 28.02.2011 - 22:09
fuente
1

Muchos de los patrones GoF clásicos se pueden implementar con delegados: por ejemplo, el patrón de comando, el patrón de visitante, el patrón de estrategia, el patrón de fábrica y el patrón de observador a menudo se pueden implementar con un simple delegado. A veces, una clase es mejor (por ejemplo, cuando un comando necesita un nombre o un objeto de estrategia debe ser serializado), pero en la mayoría de los casos, usar Action<...> o Func<...> es mucho más elegante que crear una interfaz dedicada de un solo método. / p>     

respondido por el nikie 28.02.2011 - 23:49
fuente

Lea otras preguntas en las etiquetas