2010-11-26 13 views
53

Parece que nunca entiendo por qué necesitamos delegados? Sé que son tipos de referencia inmutables que tienen referencia de un método, pero ¿por qué no podemos simplemente llamar al método directamente, en lugar de llamarlo a través de un delegado?¿Por qué necesitamos delegados de C#

Gracias

+4

Por cierto, los delegados son inmutables! –

+0

Lo siento, quise decir inmutable – InfoLearner

+1

edited =) ......... – Singleton

Respuesta

31

Por supuesto, puede llamar al método directamente en el objeto pero considere siguientes escenarios:

  1. Quiere llamar a la serie de método mediante el uso único delegado, sin necesidad de escribir gran cantidad de llamadas a métodos.
  2. Desea implementar elegantemente el sistema basado en eventos.
  3. Quiere llamar a dos métodos iguales en la firma, pero residen en diferentes clases.
  4. Quiere pasar el método como parámetro.
  5. No desea escribir muchos códigos polimórficos como en LINQ, puede proporcionar mucha implementación al método Select.
+1

Gracias por su respuesta. 1 - ¿No puedo escribir un método que luego llame a otros métodos? P.ej. CallAllMethods(); 2. ¿Por qué querríamos pasar los métodos como parámetros? ¿Podrían darme un escenario que pueda ayudarme? Gracias de nuevo. – InfoLearner

+0

@ user520692: Por supuesto, puede hacer esto y no hay ningún problema al hacerlo, pero puede pasar este delegado a otra clase y, en función de alguna condición personalizada, puede invocar al delegado. Lo mismo es cierto para su segunda pregunta, supongamos que Jon especificó arriba de Enumarable.Seleccione no sabe, cómo seleccionar los registros para pasar a un delegado que introduce puntos en un método, puede seleccionar los registros y al final NO BUDDY FORCES USTED UTILIZARÁ EL DELEGADO EN CUALQUIER ESCENARIO. – TalentTuner

+1

Claro, puede escribir un método que llame a otros métodos, pero ¿qué sucede si quiere escribir un código de caja negra que maneje las devoluciones de llamadas desde código extraño, mientras se aplica la seguridad de tipo? Los delegados proporcionan un mecanismo definido con compilador y soporte en tiempo de ejecución, en lugar de obligar a las personas a implementar las suyas propias. – Chris

16

Debido a que es posible que no tener el método que se haya escrito, o si se ha diseñado su clase de tal manera que un usuario del mismo puede decidir qué método (que el usuario escribió) que el usuario desea que su clase ejecutar.

También hacen ciertos diseños más limpios (por ejemplo, en vez de una declaración de cambio donde llama a diferentes métodos, llama al delegado pasado) y son más fáciles de entender y permiten extender su código sin cambiarlo (piense en OCP).

Los delegados también son la base del sistema de eventos: escribir y registrar controladores de eventos sin delegados sería mucho más difícil de lo que es con ellos.

Vea los diferentes Action y Func delegados en Linq - no sería tan útil sin ellos.

Habiendo dicho eso, nadie te obliga a usar delegados.

7
  1. delegados apoya Eventos
  2. delegados dan su programa de una manera de ejecutar métodos sin tener que saber exactamente lo que esos métodos son en tiempo de compilación
+0

Parece haber sido robado desde aquí: http://www.techmcq.com/question/input/output/420 –

0

Puede pensar en ellos como una construcción similar con los punteros a funciones en C/C++. Pero son más que eso en C#. Details.

+0

Mal consejero ... Imagine si no sabe 'punteros a funtions in C/C++. 'Hehhehehee –

3

Piense en los punteros de función C/C++, y cómo trata las funciones de manejo de eventos de javascript como "datos" y los pasa por alto. En lenguaje Delphi también hay tipo de procedimiento. Detrás de escena, las expresiones delegado y lambda de C#, y todas esas cosas son esencialmente la misma idea: codificar como datos. Y esto constituye la base misma de la programación funcional.

58

Respuesta simple: el código que necesita realizar la acción no conoce el método para llamar cuando está escrito. Solo puede llamar al método directamente si sabe en tiempo de compilación a qué método llamar, ¿no? Entonces, si desea abstraer la idea de "realizar la acción X en el momento apropiado", necesita alguna representación de la acción, de modo que el método que llama a la acción no necesite conocer la implementación exacta con anticipación.

Por ejemplo:

  • Enumerable.Select en LINQ no se puede conocer la proyección que desea utilizar a menos que usted le indique
  • El autor de Button no sabía lo que desea que la acción sea cuando el usuario hace clic en él
  • Si un nuevo hilo solamente nunca hizo una cosa, sería bastante aburrido ...

Puede ayudarlo a pensar que los delegados son como interfaces de un solo método, pero con una gran sintaxis de lenguaje para que sean fáciles de usar, y un soporte original para la ejecución asincrónica y la multidifusión.

+1

+1 para Enumerable.Seleccione el método – TalentTuner

+0

¿No usamos el patrón de estrategia en este escenario? –

+1

@AtishDipongkor: delega de manera efectiva * es * una implementación del patrón de estrategia, para una estrategia de método único ... pero de una manera más flexible.(La estrategia se puede implementar con un método privado, o una expresión lambda, etc.) –

3

Todo lo que se puede hacer con los delegados se puede hacer sin ellos, pero los delegados proporcionan una forma mucho más limpia de hacerlas. Si no hubiera delegados, habría que definir una interfaz o clase base abstracta para cada posible firma de función que contenga una función Invocar (parámetros apropiados) y definir una clase para cada función que fuera elegible por los pseudodelegados. Esa clase heredará la interfaz apropiada para la firma de la función, contendrá una referencia a la clase que contiene la función que supuestamente representa, y un método que implementará Invoke (parámetros apropiados) que llamaría a la función apropiada en la clase a la que pertenece. una referencia. Si la clase Foo tiene dos métodos, Foo1 y Foo2, ambos tomando un único parámetro, ambos pueden ser llamados por pseudodelegados, se crearían dos clases adicionales, una para cada método.

Sin el soporte del compilador para esta técnica, el código fuente debería ser bastante atroz. Sin embargo, si el compilador pudiera autogenerar las clases anidadas correctamente, las cosas podrían estar bastante limpias. La velocidad de despacho para los pseudodelegados probablemente sea generalmente más lenta que con los delegados convencionales, pero si los pseudodelegados fueran una interfaz en lugar de una clase base abstracta, una clase que solo necesita hacer un pseudo delegado para un método de una firma determinada podría implementar la propia interfaz de pseudo delegado; la instancia de la clase podría pasar a cualquier código esperando un pseudo delegado de esa firma, evitando la necesidad de crear un objeto adicional. Además, si bien el número de clases que uno necesitaría al usar pseudo delegados sería mayor que cuando se usan delegados "reales", cada pseudo delegado solo necesitaría tener una sola instancia de objeto.

+0

Sería genial si compartes aquí un par de muestras de eso, por favor. –

1

Pidió un ejemplo de por qué pasaría una función como parámetro, tengo una perfecta y pensé que podría ayudarlo a entender, es bastante académica pero muestra un uso. Supongamos que tiene un método ListResults() y el método getFromCache(). En lugar de tener un montón de cheques si la caché es nulo, etc. que sólo puede pasar cualquier método para getCache y sólo invocarlo si la caché está vacía dentro del método getFromCache:

_cacher.GetFromCache(delegate { return ListResults(); }, "ListResults");

public IEnumerable<T> GetFromCache(MethodForCache item, string key, int minutesToCache = 5) 
    { 
     var cache = _cacheProvider.GetCachedItem(key); 
     //you could even have a UseCache bool here for central control 
     if (cache == null) 
     { 
      //you could put timings, logging etc. here instead of all over your code 
      cache = item.Invoke(); 
      _cacheProvider.AddCachedItem(cache, key, minutesToCache); 
     }    

     return cache; 
    } 
+0

¿Podría escribir otro código mal hecho para ver por qué tenemos que hacer lo que está sugiriendo, por favor? –

+0

¡Qué horrible ejemplo, amigo! – Heliac

+0

Claro, pero sí ilustra cómo funciona un delegado. ¿Esa no era la pregunta? – GarethReid

Cuestiones relacionadas