Eventos

Concepto de evento

    Un evento es una variante de las propiedades para los campos cuyos tipos sean delegados. Es decir, permiten controlar la forman en que se accede a los campos delegados y dan la posibilidad de asociar código a ejecutar cada vez que se añada o elimine un método de un campo delegado.

Sintaxis básica de definición de eventos

    La sintaxis básica de definición de un evento consiste en definirlo como cualquier otro campo con la única peculiaridad de que se le ha de anteponer la palabra reservada event al nombre de su tipo (que será un delegado) O sea, se sigue la sintaxis:


<modificadores> event <tipoDelegado> <nombreEvento>;

    Por ejemplo, para definir un evento de nombre Prueba y tipo delegado D se haría:


public event D Prueba;

    También pueden definirse múltiples eventos en una misma línea separando sus nombres mediante comas. Por ejemplo:


public event
D Prueba1, Prueba2;

    Desde código ubicado dentro del mismo tipo de dato donde se haya definido el evento se puede usar el evento tal y como si de un campo delegado normal se tratase. Sin embargo, desde código ubicado externamente se imponen una serie de restricciones que permiten controlar la forma en que se accede al mismo:

  • No se le puede aplicar los métodos heredados de System.MulticastDelegate.

  • Sólo se le puede aplicar dos operaciones: añadido de métodos con += y eliminación de métodos con -=. De este modo se evita que se use sin querer = en vez de += ó -= y se sustituyan todos los métodos de la lista de métodos del campo delegado por otro que en realidad se le quería añadir o quitar (si ese otro valiese null, ello incluso podría provocar una System.NullReferenceException)

  • No es posible llamar a los métodos almacenados en un campo delegado a través del mismo. Esto permite controlar la forma en que se les llama, ya que obliga a que la llamada tenga que hacerse a través de algún método público definido en la definición del tipo de dato donde el evento fue definido.

Sintaxis completa de definición de eventos

La verdadera utilidad de un evento es que permite controlar la forma en que se asocian y quitan métodos de los objetos delegados con += y -=. Para ello se han de definir con la siguiente sintaxis avanzada:


<modificadores> event <tipoDelegado> <nombreEvento>
{
 add
 {
  <códigoAdd>
 }
 
 remove
 {
  <códigoRemove>
 }
}

    Con esta sintaxis no pueden definirse varios eventos en una misma línea como ocurría con la básica. Su significado es el siguiente: cuando se asocie un método con +=  al evento se ejecutará el <códigoAdd>, y cuando se le quite alguno con –= se ejecutará el <códigoRemove>. Esta sintaxis es similar a la de los bloques set/get de las propiedades pero con una importante diferencia: aunque pueden  permutarse las secciones add y remove, es obligatorio incluir siempre a ambas.

    La sintaxis básica es en realidad una forma abreviada de usar la avanzada. Así, la definición public event D Prueba(int valor); la interpretaría el compilador como:


private D prueba
public event D  Prueba
{
 [MethodImpl(MethodImlOptions.Synchronized)]
 add
 {
  prueba = (D) Delegate.Combine(prueba, value);
 }
 [MethodImpl(MethodImlOptions.Synchronized)]   
 remove
 {
  prueba = (D) Delegate.Remove(prueba, value);
 }
}

    Es decir, el compilador definirá un campo delegado privado y códigos para add y remove que hagan que el uso de += y -= sobre el evento tenga el efecto que normalmente tendrían si se aplicasen directamente sobre el campo privado. Como se ve, dentro de estos métodos se puede usar value para hacer referencia al operando derecho de los operadores += y -=. El atributo System.Runtime.InteropServices.MethodImpl que precede a los bloques add y remove sólo se incluye para asegurar que un cambio de hilo no pueda interrumpir la ejecución de sus códigos asociados.

    Las restricciones de uso de eventos desde códigos externos al tipo donde se han definido se deben a que en realidad éstos no son objetos delegados sino que el objeto delegado es el campo privado que internamente define el compilador. El compilador traduce toda llamada al evento en una llamada al campo delegado. Como este es privado, por eso sólo pueda accederse a él desde código de su propio tipo de dato.

    En realidad, el compilador internamente traduce las secciones add y remove de la definición de un evento en métodos de la forma:


void add_<nombreEvento>(<tipoDelegado> value)
void remove_<nombreEvento>(<tipoDelegado> value) 

    Toda aplicación de += y -= a un evento no es convertida en una llamada al campo privado sino en una llamada al método add/remove apropiado, como se puede observar analizando el MSIL de cualquier fuente donde se usen += y -= sobre eventos. Además, como estos métodos devuelven void ése será el tipo del valor devuelto al aplicar += ó -= (y no el objeto asignado), lo que evitará que código externo al tipo donde se haya definido el evento pueda acceder directamente al campo delegado privado.

    Si en vez de la sintaxis básica usamos la completa no se definirá automáticamente un campo delegado por cada evento que se defina, por lo que tampoco será posible hacer referencia al mismo desde código ubicado en la misma clase donde se ha definido. Sin embargo ello permite que el programador pueda determinar, a través de secciones add y remove, cómo se almacenarán los métodos. Por ejemplo, para ahorrar memoria se puede optar por usar un diccionario donde almacenar los métodos asociados a varios eventos de un mismo objeto en lugar de usar un objeto delegado por cada uno.

    Dado que las secciones add y remove se traducen como métodos, los eventos también podrán participar en el mecanismo de herencia y redefiniciones típico de los métodos. Es decir, en <modificadores> aparte de modificadores de acceso y el modificador static, también se podrán incluir los modificadores relativos a herencia. En este sentido hay que precisar algo: un evento definido como abstract ha de definirse siempre con la sintaxis básica (no incluirá secciones add o remove)

Eventos
José Antonio González Seco

José Antonio es experto en tecnologias Microsoft. Imparte cursos y conferencias en congresos sobre C# y .NET en Universidades de toda España (Sevilla, Barcelona, San Sebastián, Valencia, Oviedo, etc.) en representación de grandes empresas como Microsoft.
Fecha de alta:27/10/2006
Última actualizacion:27/10/2006
Visitas totales:52018
Valorar el contenido:
Últimas consultas realizadas en los foros
Últimas preguntas sin contestar en los foros de devjoker.com