Estoy tratando de entender Delegados en C#. Todavía no estoy demasiado metido en la madriguera del conejo; hasta donde yo sé, son solo consejos. Cometí el error de tratar de aplicar la lógica de JavaScript a C# cuando intentaba entenderlos originalmente (todo es let o const), sin embargo, pronto me di cuenta de que no había forma de asignar métodos. Entonces entiendo por qué necesitamos Delegados, mi pregunta es:
¿Por qué los declaramos?
En lugar de:
public delegate void Pointer(String text); Pointer p = SomeMethod;¿Por qué no simplemente hacer:
var p = SomeMethod;???
Estoy seguro de que debe haber algunas cosas avanzadas que aún no sé, pero no puedo ver por qué alguna vez necesitarías declararlas de la primera manera.
La mayoría de las veces encuentro que Action y Func son suficientes. Una razón por la que podría querer declararlos es para devolverlos a un controlador de eventos. Por ejemplo,
public delegate void MyEventHandler(object sender, MyEventArgs e);Y luego seguirías con eso
public event MyEventHandler OnEvent;Esto le permitiría suscribirse a ese evento, presumiblemente con argumentos personalizados en MyEventArgs. En este caso, no podría confiar en var, aunque podría usar Action para lograr un resultado similar sin declarar el prototipo de delegado:
public event Action<object, MyEventArgs> OnEvent;¿Por qué declararías al delegado? Para mí, se trata principalmente de consistencia. Declarar el delegado le brinda un lugar donde puede cambiar su código si la firma alguna vez cambia, lo que también, en mi opinión, hace que su código sea más legible.
Los tipos delegados son comúnmente necesarios si desea dar a la persona que llama a una función la posibilidad de calcular algo mientras se ejecuta el método (por ejemplo, List<T>.ForEach usa un delegado para llamar a una función definida por el usuario para cada elemento).
Un tipo de delegado se define de la siguiente manera:
<access modifier> deleage <function header>
El uso de este delegado asegura al compilador que la función toma los parámetros correctos y devuelve un valor del tipo correcto. Por supuesto, esto podría verificarse en tiempo de ejecución, pero este no es el enfoque de C#. Esto contrasta con los lenguajes de tipos dinámicos (JavaScript, Python, ...), que podrían tener la posibilidad de verificar en tiempo de ejecución si la función cumple con los requisitos.
Entonces tiene razón, teóricamente no es necesario, pero C #, Java y otros lenguajes de tipo estático solo requieren una definición de la función en alguna parte.
C# es de tipo estático. Entonces, cada objeto debe tener un tipo de datos conocido. La palabra clave var solo hace que el compilador decida el tipo de datos en lugar del programador.
Pero como está en su ejemplo, no tiene que escribir un delegado personalizado para cada cosa, hay algunos delegados estándar como Action y Function . Si su función coincide con una de esas interfaces predefinidas, puede asignarlas usando el tipo explícitamente (escribiendo el tipo de datos antes del nombre de la variable) o implícitamente tal como lo hizo con la palabra clave var .
¿Por qué los declaramos?
Declaramos todo en C#. Bueno, además de dynamic (pero aun así, es un frente para un diccionario).
¿Por qué no simplemente hacer
var p = SomeMethod;
Intente hacer eso en un proyecto de .net framework; obtendrá un error "no se puede asignar el grupo de métodos a la variable local escrita implícitamente". Algunos de los consejos que encuentra flotando en Internet son anteriores a la invención de la .net que está utilizando y, por lo tanto, se enfocan en patrones más antiguos de hacer las cosas.
Simplemente no puedo ver por qué alguna vez necesitarías declararlos de la primera manera.
Si observa la evolución de C # a lo largo del tiempo, siempre está tratando de encontrar formas de permitir que uno exprese su intención de manera más compacta / ordenada. Lo que comenzó como una sintaxis bastante detallada para (insertar operación como "declarar una propiedad" aquí) se convierte en caracteres con el tiempo, generalmente porque las partes que la gente usa mucho se vuelven tediosas para seguir escribiendo (incluso con propfull-tab-tab ) o incluso leer
Desde la introducción de los genéricos, ha sido posible usar Action<...> y Func<...> en lugar de declarar los propios tipos de delegado, pero delegar precedió a los genéricos, por lo que durante un buen tiempo usamos mucho la palabra clave delegado.
Esos años de "hacerlo de esta manera" acumulan una inercia de documentación/enseñanza que no cambia de la noche a la mañana. Nadie ve C# 10 salir e inmediatamente revisar todos sus blogs antiguos y desechar/reescribir el consejo para hacer X de alguna manera antigua que el C# más nuevo simplifica; en cambio, escriben otra publicación de blog sobre las nuevas características que generalmente ayudan a las personas a hacer la transición si están acostumbrados a la forma anterior.
También es lógico que si está aprendiendo acerca de los delegados, una búsqueda en la web mostraría un tutorial que menciona la palabra. Tal tutorial quizás comenzaría de manera más sensata en un nivel muy básico de "cómo lo hacemos" porque se relaciona con el resto de los conceptos del lenguaje: así es como declaramos una clase que representa a una persona, así es como declaramos un delegado que representa una operación que toma un int y devuelve una cadena, para que un tutorial comience con el nivel más alto de comodidad que ofrece C# y diga "simplemente diga var p = SomeMethod , y asegúrese de omitir () para que no "No llame al método, y C# hará el resto de los trucos necesarios para crear un objeto que se refiera al método" no enseña mucho sobre lo que sucede debajo del capó.
Como relativamente nuevo sin ese conocimiento previo de cómo se relacionaba, lo está relacionando con otros lenguajes, lo que puede ser problemático (especialmente algo bastante rápido y suelto como JavaScript), pero en las versiones recientes de C# absolutamente puede haz lo que propongas ( var p = SomeMethod ). Si obtiene un trabajo con un código base de N años, probablemente encontrará delegate ... allí en alguna parte, por lo que tener la familiaridad con él que ha adquirido lo ayudará a leerlo incluso si no puede migrarlo a un más moderno. encarnación..