Pregunta

Supongamos que tenemos:

interface Foo 
{
 bool Func(int x);
}

class Bar: Foo
{
  bool Func(int x)
  {
   return (x>0);
  }  
}

class Baz: Foo
{
  bool Func(int x)
  {
   return (x<0);
  }  
}

Ahora podemos utilizar Bar y Baz como Foos y llamar a sus métodos Func.

Los delegados simplifican esto un poco:

delegate bool Foo(int x);

bool Bar(int x)
{
 return (x<0);
}

bool Baz(int x)
{
 return (x>0);
}

Ahora podemos jugar con Bar y Baz como delegados de Foo.

¿Cuál es el beneficio real de los delegados, excepto obtener un código más corto?

¿Fue útil?

Solución

Hay una ligera diferencia, los delegados pueden acceder a las variables miembro de las clases en las que están definidos.En C# (a diferencia de Java), todas las clases internas se consideran estáticas.Por lo tanto, si está utilizando una interfaz para gestionar una devolución de llamada, p.un ActionListener para un botón.A la clase interna implementadora se le deben pasar (a través del constructor) referencias a las partes de la clase contenedora con las que puede necesitar interactuar durante la devolución de llamada.Los delegados no tienen esta restricción, por lo que reducen la cantidad de código necesario para implementar la devolución de llamada.

Un código más corto y conciso también es un beneficio que vale la pena.

Otros consejos

Desde la perspectiva de la ingeniería de software, tiene razón, los delegados se parecen mucho a las interfaces de funciones en el sentido de que crean un prototipo de una interfaz de funciones.

También se pueden utilizar de la misma manera:en lugar de pasar una clase completa que contiene el método que necesita, puede pasar solo un delegado.Esto ahorra una gran cantidad de código y crea un código mucho más legible.

Además, con la llegada de las expresiones lambda, ahora también se pueden definir fácilmente sobre la marcha, lo cual es una gran ventaja.Si bien es POSIBLE crear clases sobre la marcha en C#, es realmente un gran dolor de cabeza.

Comparar los dos es un concepto interesante.No había considerado previamente cuán parecidas son las ideas desde el punto de vista del caso de uso y la estructuración del código.

Un delegado tiene mucho en común con una referencia de interfaz que tiene un único método desde el punto de vista de la persona que llama.

En el primer ejemplo, Baz y Bar son clases que se pueden heredar y crear instancias.En el segundo ejemplo, Baz y Bar son métodos.

No puede aplicar referencias de interfaz a cualquier clase que coincida con el contrato de interfaz.La clase debe declarar explícitamente que admite la interfaz.Puede aplicar una referencia de delegado a cualquier método que coincida con la firma.

No puede incluir métodos estáticos en el contrato de una interfaz.(Aunque puede incorporar métodos estáticos con métodos de extensión).Puede hacer referencia a métodos estáticos con una referencia de delegado.

No, los delegados son para punteros de métodos.Luego puede asegurarse de que la firma del método asociado con el delegado sea correcta.

Además, no es necesario conocer la estructura de la clase.De esta manera, puede usar un método que haya escrito para pasarlo a un método en otra clase y definir la funcionalidad que desea que suceda.

Échale un vistazo al Clase List<> con el método Find.Ahora puede definir qué determina si algo coincide o no, sin necesidad de que los elementos contenidos en la clase implementen IListFindable o algo similar.

Puedes pasar delegados como parámetros en funciones (bueno, técnicamente los delegados se convierten en objetos cuando se compilan, pero ese no es el punto aquí).Podrías pasar un objeto como parámetro (obviamente), pero luego estás vinculando ese tipo de objeto a la función como parámetro.Con los delegados puedes pasar cualquier función para ejecutar en el código que tenga la misma firma sin importar de dónde venga.

Se puede pensar en los delegados como una interfaz para un método que define qué argumentos y tipo de retorno debe tener un método para adaptarse al delegado.

Sí, se puede considerar a un delegado como una interfaz con un método.

Un delegado es un puntero a un método escrito.Esto le brinda más flexibilidad que las interfaces porque puede aprovechar la covarianza y la contravarianza, y puede modificar el estado del objeto (tendría que pasar este puntero con functores basados ​​en interfaz).

Además, los delegados tienen una gran cantidad de azúcar sintáctico agradable que le permite hacer cosas como combinarlos fácilmente.

Las interfaces y los delegados son dos cosas completamente diferentes, aunque entiendo la tentación de describir a los delegados en términos similares a los de una interfaz para facilitar la comprensión... sin embargo, no saber la verdad puede generar confusión en el futuro.

Los delegados se sintieron inspirados (en parte) porque el arte negro de los punteros del método C++ era inadecuado para ciertos propósitos.Un ejemplo clásico es la implementación de un mecanismo de transmisión de mensajes o de manejo de eventos.Los delegados le permiten definir la firma de un método sin ningún conocimiento de los tipos o interfaces de una clase. Podría definir un delegado "void eventHandler(Event* e)" e invocarlo en cualquier clase que lo implemente.

Para obtener una idea de este problema clásico y de por qué son deseables los delegados Lee esto y luego este.

En al menos una propuesta para agregar cierres (es decir,delegados anónimos) a Java, son equivalentes a interfaces con un método de un solo miembro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top