Delegados del sistema de tipos común

Actualización: noviembre 2007

El motor en tiempo de ejecución admite tipos de referencia denominados delegados cuya finalidad es parecida a la de los punteros a función de C++. A diferencia de los punteros a función, los delegados son seguros, se pueden comprobar y proporcionan seguridad de tipos. Un tipo de delegado puede representar cualquier método con una firma compatible. Mientras que los punteros a función sólo pueden representar funciones estáticas, un delegado puede representar tanto métodos estáticos como de instancia. Los delegados se utilizan para los controladores de eventos y las funciones de devolución de llamada en .NET Framework.

Nota:

Common Language Runtime no admite la serialización de métodos globales, por lo que no se pueden utilizar los delegados para ejecutar métodos globales en otros dominios de aplicación.

Todos los delegados heredan de MulticastDelegate, que hereda de Delegate. Los lenguajes C#, Visual Basic y C++ no permiten la herencia a partir de estos tipos; en su lugar, proporcionan palabras clave para declarar delegados.

Además de los métodos heredados, Common Language Runtime proporciona dos métodos especiales para los tipos de delegado: BeginInvoke y EndInvoke. Para obtener más información acerca de estos métodos, consulte Llamar a métodos sincrónicos de forma asincrónica.

Dado que los delegados heredan de MulticastDelegate, un delegado tiene una lista de invocación, que es una lista de métodos que representa el delegado y que se ejecutan cuando se llama al delegado. Todos los métodos de la lista reciben los argumentos proporcionados cuando se invoca al delegado.

Nota:

El valor devuelto no se define para los delegados que tienen más de un método en su lista de invocación, aunque el delegado tenga un tipo de valor devuelto.

Crear y utilizar delegados

En muchos casos, como en el de los métodos de devolución de llamada, un delegado sólo representa un método y las únicas acciones que es necesario llevar a cabo se limitan a crear el delegado e invocarlo.

Por lo que se refiere a los delegados que representan varios métodos, .NET Framework proporciona métodos de las clases de delegado Delegate y MulticastDelegate para operaciones tales como agregar un método a una lista de invocación del delegado (el método Delegate.Combine), quitar un método (el método Delegate.Remove) y obtener la lista de invocación (el método Delegate.GetInvocationList).

Nota:

No es preciso utilizar estos métodos para delegados de controladores de eventos en C#, C++ ni Visual Basic, ya que estos lenguajes proporcionan sintaxis para agregar y quitar controladores de eventos.

Delegados estáticos cerrados y delegados de instancia abiertos

Los delegados pueden representar métodos static (Shared en Visual Basic) o métodos de instancia. Por lo general, cuando un delegado representa un método de instancia, la instancia se enlaza al delegado junto con el método. Por ejemplo, un delegado de controladores de eventos podría tener tres métodos de instancia en su lista de invocación, cada uno de ellos con una referencia al objeto al que pertenece el método.

En la versión 2.0 de .NET Framework también es posible crear un delegado abierto para un método de instancia. Un método de instancia tiene un parámetro de instancia implícito (representado por this en C# o por Me en Visual Basic) y se puede representar mediante un tipo de delegado que exponga este parámetro oculto. Es decir, el tipo de delegado debe tener un parámetro adicional al principio de su lista de parámetros formales, del mismo tipo que la clase a la que pertenece el método. También se admite una situación opuesta a la de este escenario, de modo que es posible enlazar el primer argumento de un método estático.

Nota:

La creación de delegados de instancia abiertos y estáticos cerrados no está admitida directamente en Visual Basic, C++ o C# para constructores delegados. En su lugar, debe utilizarse una de las sobrecargas de método Delegate.CreateDelegate que especifica objetos MethodInfo, como Delegate.CreateDelegate(Type, Object, MethodInfo, Boolean).

Reglas relajadas para enlace de delegado

En .NET Framework versión 2.0, los tipos de parámetros y el tipo de valor devuelto de un delegado debe ser compatible con los tipos de parámetros y el tipo de valor devuelto del método que representa el delegado; los tipos no tienen que coincidir exactamente.

Nota:

En las versiones 1.0 y 1.1 de .NET Framework los tipos deben coincidir exactamente.

Un parámetro de un delegado es compatible con el parámetro correspondiente de un método si el tipo del parámetro del delegado es más restrictivo que el tipo del parámetro del método, dado que así se garantiza que un argumento pasado al delegado se pueda pasar al método de un modo seguro.

Asimismo, el tipo de valor devuelto de un delegado es compatible con el tipo de valor devuelto de un método si el tipo de valor devuelto del método es más restrictivo que el tipo de valor devuelto del delegado, dado que así se garantiza que el valor devuelto del método pueda convertirse de un modo seguro al tipo de valor devuelto del delegado.

Por ejemplo, un delegado con un parámetro de tipo Hashtable y un tipo de valor devuelto Object puede representar un método con un parámetro de tipo Object y un valor devuelto de tipo Hashtable.

Para obtener más información y código de ejemplo, vea Delegate.CreateDelegate(Type, Object, MethodInfo).

Delegados y llamadas asincrónicas a métodos

Cada delegado tiene un método BeginInvoke que permite llamar de forma asincrónica al delegado, así como un método EndInvoke que limpia después los recursos. Estos métodos se generan automáticamente para cada tipo de delegado. Cuando se invoca un delegado con el método BeginInvoke, el método que representa el delegado se ejecuta en un subproceso que pertenece a un objeto ThreadPool.

Para obtener más información y código de ejemplo, vea Programación asincrónica mediante delegados.

Vea también

Conceptos

Utilizar eventos

Eventos y delegados

Referencia

System.Delegate

System.EventHandler

Otros recursos

Sistema de tipos comunes

Programación asincrónica mediante delegados