¿Qué es delegado? [cerrado]

152

Estoy confundido de cuál es el papel real de un delegado?

Me han hecho esta pregunta muchas veces en mis entrevistas, pero no creo que los entrevistadores estuvieran satisfechos con mi respuesta.

¿Alguien puede decirme la mejor definición, en una oración, con un ejemplo práctico?

Naveed
fuente
21
por curiosidad, ¿qué respondiste para que podamos decirte cómo puedes corregirlo?
Anthony Forloney el
66
Me parece interesante que esta pregunta se haya cerrado pero que tenga 126 votos a favor y 65 personas la hayan marcado como favorita. Parece que incluso si es demasiado amplio, sigue siendo una muy buena pregunta.
Rico

Respuestas:

171

Me gusta pensar en un delegado como "un puntero a una función". Esto se remonta a los días C, pero la idea aún se mantiene.

La idea es que necesita poder invocar un fragmento de código, pero ese fragmento de código que va a invocar no se conoce hasta el tiempo de ejecución. Entonces usas un "delegado" para ese propósito. Los delegados son útiles para cosas como controladores de eventos, y tal, donde haces diferentes cosas basadas en diferentes eventos, por ejemplo.

Aquí hay una referencia para C # que puede ver:

En C #, por ejemplo, digamos que teníamos un cálculo que queríamos hacer y queríamos usar un método de cálculo diferente que no conocemos hasta el tiempo de ejecución. Entonces podríamos tener un par de métodos de cálculo como este:

public static double CalcTotalMethod1(double amt)
{
    return amt * .014;
}

public static double CalcTotalMethod2(double amt)
{
    return amt * .056 + 42.43;
}

Podríamos declarar una firma de delegado como esta:

public delegate double calcTotalDelegate(double amt);

Y luego podríamos declarar un método que tome al delegado como un parámetro como este:

public static double CalcMyTotal(double amt, calcTotalDelegate calcTotal)
{
    return calcTotal(amt);
}

Y podríamos llamar al CalcMyTotalmétodo pasando el método delegado que queríamos usar.

double tot1 = CalcMyTotal(100.34, CalcTotalMethod1);
double tot2 = CalcMyTotal(100.34, CalcTotalMethod2);
Console.WriteLine(tot1);
Console.WriteLine(tot2);
dcp
fuente
19
+1 por el guiño al puntero de función simple pero efectivo en C.
Aiden Bell
3
Una pregunta relacionada con tu respuesta. ¿Cómo es realmente diferente de llamar a una función de manera normal? ¿Solo por eso no se conoce en tiempo de ejecución?
Naveed
1
@NAVEED: consulte mi última edición, incluí un ejemplo. En cuanto a la llamada al método real, no se ve diferente de una llamada al método normal en mi ejemplo anterior (el calcTotal (amt) está llamando al delegado), pero el poder de los delegados es que puede usarlos como parámetros, etc. cuando desee un método para poder tener un comportamiento diferente. Hay muchas otras cosas para las que también puede usarlas, este es solo un ejemplo simple. Espero que ayude.
dcp
No se conoce en tiempo de ejecución, y es una función enlazada en lugar de una función libre: asignar un método no estático Fooa un delegado llamará en this.Foo()lugar de una función estática como lo haría un puntero de función (en C, a menudo tiene un void*parámetro adicional para pase thisal puntero de función)
Pete Kirkham
1
+1 para el ejemplo rápido y efectivo que establece similitudes con punteros de función en C / C ++. ¡Muy apreciado!
G21
19

un delegado es simplemente un puntero de función.
simplemente asigne el método que desea ejecutar su delegado. luego, en el código, puede llamar a ese método mediante Invoke

algún código para demostrar (escribió esto desde la memoria, por lo que la sintaxis puede estar desactivada)

delegate void delMyDelegate(object o);

private void MethodToExecute1(object o)
{
    // do something with object
}

private void MethodToExecute2(object o)
{
    // do something else with object
}

private void DoSomethingToList(delMyDelegate methodToRun)
{
    foreach(object o in myList)
        methodToRun.Invoke(o);
}

public void ApplyMethodsToList()
{
    DoSomethingToList(MethodToExecute1);
    DoSomethingToList(MethodToExecute2);
}
Mladen Prajdic
fuente
16

Tomado de aquí

P ¿Qué son los delegados?
A Cuando un objeto recibe una solicitud, el objeto puede manejar la solicitud o pasar la solicitud a un segundo objeto para hacer el trabajo. Si el objeto decide pasar la solicitud, usted dice que el objeto ha enviado la responsabilidad de manejar la solicitud al segundo objeto.

O, como un pseudo ejemplo fácil: algo envía una solicitud a object1. object1 luego reenvía la solicitud y a sí mismo a object2: el delegado. object2 procesa la solicitud y hace algo de trabajo. (nota: el enlace de arriba da buenos ejemplos)

Anthony Forloney
fuente
El ejemplo dado en el enlace anterior no indica correctamente la delegación.
Hardik9850
4

Piense en delegado como en una implementación simplificada del patrón de comando.

Vitaliy Liptchinsky
fuente
4

Un delegado es un objeto que puede referirse a un método. Por lo tanto, cuando creamos un delegado, estamos creando un objeto que puede contener una referencia a un método. Además, el método puede llamarse a través de esta referencia. Por lo tanto, un delegado puede invocar el método al que se refiere. La principal ventaja de un delegado es que nos permite especificar una llamada a un método, pero el método realmente invocado se determina en tiempo de ejecución, no en tiempo de compilación.

Delegado simple

Declaration of delegate:
delegate-modifier delegate return-type delegate-name(parameters)
Implementation of delegate:
Delegate-name delegate-object=new Delegate-name(method of class)

http://knowpacific.wordpress.com/2012/01/26/delegate/

Sandeep Shekhawat
fuente
2

Aquí voy a explicar delegados, delegados de multidifusión y su uso. Delegado es un tipo que contiene la referencia de método (s) en un objeto. También se conoce como puntero de función de tipo seguro. Podemos decir que un delegado es un tipo que define la firma de un método.

Cuando crea una instancia de un delegado, puede asociar su instancia con cualquier método con una firma compatible. Puede invocar (o llamar) el método a través de la instancia de delegado. Los delegados se utilizan para pasar métodos como argumentos a otros métodos. Los controladores de eventos no son más que métodos que se invocan a través de delegados. Las ventajas de usar delegados son: encapsular la llamada del método de la persona que llama. El uso efectivo del delegado mejora el rendimiento de la aplicación. Se usa para llamar a un método de forma asincrónica. Hay algunas propiedades de los delegados son

Delegates are like C++ function pointers but are type safe.
Delegates allow methods to be passed as parameters.
Delegates can be used to define callback methods.
Delegates can be chained together; for example, multiple methods can be called on a single event.
Methods do not have to match the delegate signature exactly.

delegado público type_of_delegate delegate_name () // Declaración

You can use delegates without parameters or with parameter list
If you are referring to the method with some data type then the delegate which you are declaring should be in the same format. This is why it is referred to as type safe function pointer. Here I am giving an example with String.

El siguiente ejemplo muestra una operación de delegado:

    namespace MyDelegate
    {
        class Program
        {
            private delegate void Show(string s);


            // Create a method for a delegate.
            public static void MyDelegateMethod(string me

ssage)
        {
            System.Console.WriteLine(message);
        }

        static void Main(string[] args)
        {
            Show p = MyDelegateMethod;
            p("My Delegate");
            p.Invoke("My Delegate");
            System.Console.ReadLine();
        }
    }
}

¿Qué es el delegado de multidifusión?

Es un delegado que tiene la referencia de más de un método. Los delegados de multidifusión solo deben contener métodos que devuelvan nulo; de lo contrario, hay una excepción en tiempo de ejecución.

 delegate void MyMulticastDelegate(int i, string s);
 Class Class2
 {
  static void MyFirstDelegateMethod(int i, string s)
  {
    Console.WriteLine("My First Method");
  }

  static void MySecondDelegateMethod(int i, string s)
  {
    Console.WriteLine("My Second Method");
  }

  static void Main(string[] args)
  {
    MyMulticastDelegate Method= new MyMulticastDelegate(MyFirstDelegateMethod);
    Method+= new MyMulticastDelegate (MySecondDelegateMethod);
    Method(1,"Hi");             // Calling 2 Methodscalled
    Method-= new MyMulticastDelegate (MyFirstDelegateMethod);
    Method(2,"Hi");             //Only 2nd Method calling
  }
}

Aquí Delegado se agrega usando el operador + = y se elimina usando el operador - =.

Los tipos de delegado se derivan de la clase Delegado en .NET Framework. Los tipos de delegado están sellados; no se pueden derivar. Debido a que el delegado instanciado es un objeto, puede pasarse como un parámetro o asignarse a una propiedad. Esto permite que un método acepte un delegado como parámetro y llame al delegado en algún momento posterior. Esto se conoce como una devolución de llamada asincrónica.

Jom George
fuente
1

Puede encontrar una gran explicación e implementación práctica del patrón Delegado en las Clases de reenvío de colecciones de Google (también, el patrón Decorador).

Carl
fuente
1

En el evento, el remitente de la comunicación no sabe qué objeto manejará el evento. Delegado es el tipo que contiene la referencia del método. El delegado tiene firma y tiene referencia al método que coincide con su firma, por lo que el delegado es como un puntero de función de tipo seguro.

button1.Click + = new System.EventHandler (button1_Click) System.EventHandler se declara como delegado aquí. En .net Events se trabaja en el concepto de Delegado (como Button Click)

Delegate se usa cuando no sabe qué código invocar en tiempo de ejecución. Entonces, Delegate se usa para manejar eventos

http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx

Yogesh
fuente
1

Un objeto delegado es un objeto que otro objeto consulta cuando algo sucede en ese objeto. Por ejemplo, su técnico de reparaciones es su delegado si algo le sucede a su automóvil. usted va a su técnico de reparación y le pide que repare el automóvil por usted (aunque algunos prefieren reparar el automóvil ellos mismos, en cuyo caso, ellos son sus propios delegados).


fuente
1

Un delegado es un objeto que representa un puntero a una función. Sin embargo, no es un puntero de función ordinario en el sentido de que:

1) Está orientado a objetos

2) Es de tipo seguro, es decir, solo puede apuntar a un método y no puede leer la dirección de memoria sin procesar a la que apunta

3) Está fuertemente tipado. Solo puede señalar métodos que coincidan con sus firmas.

4) Puede apuntar a más de un método al mismo tiempo.

Enfriador de agua v2
fuente
1

Delegados se usa principalmente con eventos.

La necesidad es:

No desea ejecutar un fragmento de código en el momento en que ejecuta el programa. Después de ejecutar el programa, desea ejecutar ese fragmento de código cada vez que ocurre un evento.

Ejemplo:

  1. Aplicación de consola : el código solo se puede ejecutar en el momento en que ejecuta el programa. (Escrito dentro del método principal)
  2. Aplicación de Windows (programación de la interfaz de usuario): el código se puede ejecutar al hacer clic en el botón después de ejecutar el programa.

Esto es lo que dicen, no sabes qué método invocará en el momento de la compilación. solo lo sabes en tiempo de ejecución cuando haces clic en el botón.

Sin delegados no es posible programar la interfaz de usuario. Debido a que está ejecutando código cada vez que el usuario realiza eventos haciendo clic en el botón, escribiendo en el cuadro de texto, seleccionando el elemento de la lista desplegable, etc.

shathar khan
fuente
0

Un delegado es algo en lo que se delega una tarea. El objetivo principal de la delegación es desacoplar el código y permitir una mayor flexibilidad y reutilización.

En la programación, y específicamente en la programación orientada a objetos, esto significa que cuando se llama a un método para realizar algún trabajo, pasa el trabajo al método de otro objeto al que hace referencia. La referencia podría apuntar a cualquier objeto que deseemos, siempre que el objeto se ajuste a un conjunto predefinido de métodos. Lo llamamos "programación a una interfaz" (versus programación a una implementación de clase concreta). Una interfaz es básicamente una plantilla genérica y no tiene implementación; simplemente significa una receta, un conjunto de métodos, precondiciones y postcondiciones (reglas).

Ejemplo simple:

SomeInterface
{
   public void doSomething();
}


SomeImplementation implements SomeInterface
{
   public void doSomething()
   {
      System.err.println("Was it good for you?");
   }

}


SomeCaller
{
   public void doIt(SomeInterface someInterface)
   {
      someInterface.doSomething();
   }
}

Ahora puede ver que puedo usar cualquier implementación que quiera en cualquier momento sin cambiar el código en SomeCaller porque el tipo que doIt()se pasa no es concreto, sino abstracto, ya que es una interfaz. En el mundo de Java, esto a menudo se expresa en el paradigma del servicio en el que llama a un servicio (un objeto que se anuncia a sí mismo como un servicio a través de una interfaz específica) y luego el servicio llama a los delegados para que lo ayuden a hacer su trabajo. Los métodos del servicio se denominan tareas de grano grueso (makePayment (), createNewUser (), etc.), mientras que internamente hace mucho si el trabajo minucioso es a través de la delegación, con los tipos de delegados como interfaces en lugar de implementaciones concretas.

SomeService
{
    SomeInterface someImplementation = ... // assign here
    SomeOtherInterface someOtherImplementation = ... // okay, let's add a second

    public void doSomeWork()
    {
         someImplementation.doSomething();
         someOtherImplementation.doSomethingElse();
    }
}

(Nota: cómo se asigna una implementación está más allá del alcance de este hilo. Inversión de búsqueda de control e inyección de dependencia).

Acuarela
fuente
-2

Si bien no es realmente un "puntero de función", un delegado podría verse como si fuera un lenguaje dinámico como PHP:



$func = 'foo';
$func();

function foo() {
    print 'foo';
}

o en JavaScript podrías hacer algo como:


var func = function(){ alert('foo!'); }
func();

mmattax
fuente
2
Este no es un ejemplo de delegación. En su ejemplo, está utilizando lo que se llama una función variable que básicamente busca una función que tenga el mismo nombre que la cadena a la que se refiere una variable. Ver funciones variables: php.net/manual/en/functions.variable-functions.php
Aquarelle