Un delegado es una forma de puntero de función de tipo seguro utilizado por Common Language Infrastructure (CLI). Los delegados especifican un método para llamar y, opcionalmente, un objeto para llamar al método. Los delegados se utilizan, entre otras cosas, para implementar devoluciones de llamada y detectores de eventos . Un objeto delegado encapsula una referencia a un método. Luego, el objeto delegado se puede pasar al código que puede llamar al método referenciado , sin tener que saber en el momento de la compilación qué método se invocará.
Un delegado de multidifusión es un delegado que apunta a varios métodos. [1] [2] La delegación de multidifusión es un mecanismo que proporciona funcionalidad para ejecutar más de un método. Existe una lista de delegados que se mantiene internamente y, cuando se invoca al delegado de multidifusión, se ejecuta la lista de delegados.
En C #, los delegados se utilizan a menudo para implementar devoluciones de llamada en la programación impulsada por eventos. Por ejemplo, se puede usar un delegado para indicar qué método debe llamarse cuando el usuario hace clic en algún botón. Los delegados permiten al programador notificar a varios métodos que ha ocurrido un evento. [3]
Ejemplo de código C #
Código para declarar un delegatetipo, named SendMessageDelegate, que toma a Messagecomo parámetro y devuelve void:
delegado void SendMessageDelegate ( mensaje de mensaje );
Código para definir un método que toma un delegado instanciado como argumento:
void SendMessage ( SendMessageDelegate sendMessageDelegateReference ) { // Llame al delegado ya cualquier otro delegado encadenado sincrónicamente. sendMessageDelegateReference ( new Message ( "hola, este es un mensaje de muestra" )); }
El método implementado que se ejecuta cuando se llama al delegado:
void HandleSendMessage ( Message message ) { // La implementación para las clases Sender y Message no son relevantes para este ejemplo. Remitente . Enviar ( mensaje ); }
Código para llamar al método SendMessage, pasando un delegado instanciado como argumento:
SendMessage ( nuevo SendMessageDelegate ( HandleSendMessage ));
Delegados (C #)
notificador de vacío delegado ( remitente de cadena ); // Firma del método normal con la palabra clave delegado Notificador greetMe ; // Variable delegadavoid HowAreYou ( remitente de cadena ) { Console . WriteLine ( "Cómo estás," + remitente + '?' ); } greetMe = nuevo notificador ( HowAreYou );
Una variable delegada llama al método asociado y se llama de la siguiente manera:
greetMe ( "Anton" ); // Llama a HowAreYou ("Anton") e imprime "¿Cómo estás, Anton?"
Las variables delegadas son objetos de primera clase del formulario y se pueden asignar a cualquier método de coincidencia o al valor . Almacenan un método y su receptor sin ningún parámetro: [4]new DelegateType(obj.Method)
null
nuevo DelegateType ( funnyObj . HowAreYou );
El objeto funnyObj
puede ser this
omitido. Si el método lo es static
, no debería ser el objeto (también llamado instancia en otros lenguajes), sino la clase en sí. No debería ser abstract
, pero podría ser new
, override
o virtual
.
Para llamar a un método con un delegado con éxito, la firma del método tiene que coincidir con el DelegateType
con el mismo número de parámetros del mismo tipo ( ref
, out
, value
) con el mismo tipo (incluyendo el tipo de retorno).
Delegados de multidifusión (C #)
Una variable delegada puede contener varios valores al mismo tiempo:
void HowAreYou ( remitente de cadena ) { Console . WriteLine ( "Cómo estás," + remitente + '?' ); } void HowAreYouToday ( remitente de cadena ) { Console . WriteLine ( "¿Cómo estás hoy," + remitente + '?' ); } Notificador greetMe ;greetMe = HowAreYou ; greetMe + = HowAreYouToday ;greetMe ( "Leonardo" ); // "¿Cómo estás, Leonardo?" // "¿Cómo estás hoy, Leonardo?"greetMe - = HowAreYou ;greetMe ( "Pereira" ); // "¿Cómo estás hoy, Pereira?"
Si el delegado de multidifusión es una función o no tiene out
parámetro, se devuelve el parámetro de la última llamada. [5]
Detalles técnicos de implementación
Aunque las implementaciones internas pueden variar, las instancias delegadas pueden considerarse como una tupla de un objeto y un puntero de método y una referencia (posiblemente nula) a otro delegado. Por tanto, una referencia a un delegado es posiblemente una referencia a varios delegados. Cuando el primer delegado haya terminado, si su referencia de cadena no es nula, se invocará al siguiente y así sucesivamente hasta que la lista esté completa. Este patrón permite que un evento tenga una escala de gastos generales fácilmente desde la de una única referencia hasta el envío a una lista de delegados, y se usa ampliamente en la CLI.
Actuación
El rendimiento de los delegados solía ser mucho más lento que una llamada de método virtual o de interfaz (de 6 a 8 veces más lento en los puntos de referencia de Microsoft 2003), [6] pero, desde el .NET 2.0 CLR en 2005, es casi lo mismo que las llamadas de interfaz. [7] Esto significa que hay una pequeña sobrecarga adicional en comparación con las invocaciones de métodos directos.
Existen reglas muy estrictas sobre la construcción de clases delegadas. Estas reglas permiten optimizar los compiladores con un gran margen de maniobra al optimizar los delegados y, al mismo tiempo, garantizar la seguridad de los tipos. [ cita requerida ]
Ver también
Referencias
- ^ Artículo de Microsoft Developer Network (MSDN) , Cómo: combinar delegados (delegados de multidifusión) (Guía de programación de C #) , consultado el 20 de mayo de 2008
- ^ "Acerca de los" delegados "de Microsoft " . Sun Developer Network . Sun Microsystems. Archivado desde el original el 10 de febrero de 1999.
- ^ Wikilibros: Programación de C Sharp / Delegados y eventos
- ^ Mössenböck, Hanspeter (25 de marzo de 2002). "C # avanzado: número variable de parámetros" (PDF) . http://ssw.jku.at/Teaching/Lectures/CSharp/Tutorial/ : Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik. págs. 23-24 . Consultado el 4 de agosto de 2011 .
- ^ Mössenböck, Hanspeter (25 de marzo de 2002). "C # avanzado: número variable de parámetros" . Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik. pag. 25 . Consultado el 4 de agosto de 2011 .
- ^ Gray, Jan (junio de 2003). "Escribir código administrado más rápido: saber lo que cuestan las cosas" . Microsoft . Consultado el 9 de septiembre de 2007 .
- ^ Sturm, Oliver (1 de septiembre de 2005). "Las llamadas de los delegados se aceleraron enormemente en .NET 2" . Consultado el 9 de septiembre de 2007 .
enlaces externos
- Documentación de MSDN para delegados
- Libro blanco de Sun sobre los delegados
- Respuesta de Microsoft a Sun