jueves, 5 de junio de 2014

Eventos en C# - Parte 3: Funciones de Acceso de Eventos

Índice

0. Introducción
1. Funciones de Acceso (Accesors) de Eventos
1.1 Implementación personalizada de las funciones de acceso
1.2 Estrategias de uso de funciones de acceso explícitas
1.2.1 Ejemplo de interfaz con evento 
1.2.2 Ejemplo de mecanismo de almacenamiento interno para eventos
2. Conclusiones
3. Glosario
4. Literatura & Enlaces

0. Introducción

En este penúltimo artículo de la serie de eventos en C#, nos centraremos en explorar las oportunidades que brinda la personalización de las funciones de acceso de eventos. Encontraremos su utilidad en aplicaciones que requieren un alto desempeño, y cualquier byte desperdiciado es un coste en la memoria disponible de la infraestructura de cómputo en la que se ejecuta nuestra aplicación.

1. Funciones de Acceso (Accesors) de Eventos

De acuerdo con [1], las funciones de acceso (accesors) de eventos corresponden con las implementaciones de los operadores compuestos de suma y resta. A nombrar: +=, y -=. El compilador de C# se encarga implementar de forma automática las funciones de acceso para estos operadores. Si tomamos el siguiente ejemplo:

public event EventHandler PrecioCambio;

el compilador hará lo siguiente:
  • Generación de un campo privado para el delegado.
  • Generación de las funciones de acceso para la agregación y remoción de manejadores o listeners de eventos:

    add_PrecioCambio

    remov_PrecioCambio

    Estas dos funciones de acceso corresponden con los operadores compuestos de suma y resta, += y -=, respectivamente.
Sin embargo, C# permite al programador crear declaraciones personalizadas de estas funciones de acceso.

1.1 Implementación personalizada de las funciones de acceso

En la clase publicadora (o broadcaster) podemos crear las funciones de acceso para los eventos declarados en la misma. Para poner como caso, creemos la implementación personalizada para el evento de la sección inmediatamente anterior (i.e., PrecioCambio):

private EventHandler _precioCambio;

public event EventHandler PrecioCambio
{
add
{
_precioCambio += value;
}
remove
{
_precioCambio -= value;
}
}

Esta declaración explícita de las funciones de acceso del evento son similares a la sintaxis declarativa para las propiedades (Propiedades en C#). Sin embargo, hay algunas particularidades a considerar, y son las siguientes:
  • Uso explícito de la palabra clave add para el bloque de la función de acceso para agregar un nuevo listener (o clase cliente interesada en escuchar el evento).
  • Uso explícito de la palabra clave remove para el bloque de declaración de la función de acceso de remoción de un listener (clase interesada en escuchar el evento).
Por otro lado, hay que considerar y tener en cuenta que la especificación explícita de las funciones de acceso de un evento, automáticamente remueve algunas características de programación de multi-hilos [1]. El mismo ejemplo anterior, pero agregaremos la protección para bloque en un ambiente sincrónico (más adelante vendrán artículos dedicados este importante tema):

public event EventHandler PrecioCambio
{
add
{
lock (_precioCambio)
{
 _precioCambio += value;
}
}
remove
{
lock (_precioCambio)
{
_precioCambio -= value;
}
}
}

Con el uso de la sentencia lock [3] bloqueamos el acceso concurrente al bloque de código encerrado por esta sentencia.

1.2 Estrategias de uso de funciones de acceso explícitas

En [1] se nombran algunos escenarios en donde la implementación explícita de funciones de acceso es crucial:
  1. En las funciones de acceso add y remove requerimos especificar un tipo que se encarga de la reacción frente a la generación de eventos, en lugar de la clase contenedora de la declaración evento.

  2. Si una clase broadcaster (emisora, o publicadora) está compuesta por decenas de eventos y el consumo de recursos de sistema sea un tema crucial para el desempeño de la aplicación; entonces se recomienda el uso de una estructura de datos contenedora. En [1] recomiendan el uso de un diccionario, debido a que éste gestiona eficientemente valores null.

  3. Se posee un contrato en una interfaz que contiene un evento abstracto.

1.2.1 Ejemplo de interfaz con evento

Para el último escenario de la sección 1.2, este ejemplo puede ayudar a comprender su utilidad:

public interface IInterfaz
{
private EventHandler Evento;
}

Ahora implementamos el evento de explícitamente (Interfaces en C# - Parte 5):

class ClaseBroadcaster : IInterfaz
{
private EventHandler evento;
event EventHandler IInterfaz.Evento
{
add
{
evento += value;
}
remove
{
evento -= value;
}
}
}

1.2.2 Ejemplo de mecanismo de interno de almacenamiento para eventos

En el siguiente ejemplo la clase Control implementa un sistema de almacenamiento interno para los eventos que general el control (Component):

Archivo de código fuente Control.cs [enlace alternativo]:

En los métodos ObtenerEventHandlerAgregarEventHandler, y RemoverEventHandler podemos implementar un mecanismo de almacenamiento interno para los manejadores de eventos. Aquí podemos poner en marcha la estrategia 2 de la sección 1.2.

[Nota: para mayor información recomiendo la lectura de [6, 7].]

2. Conclusiones

En este parte hemos comprendido el uso de las funciones de acceso explícitas de los eventos. La implementación explícita de la agregación y remoción se ajusta a escenarios de optimización del almacenamiento interno de los manejadores de eventos (delegados, o event handlers). Igualmente, tratamos un caso de delegado abstracto (declarado en una interfaz) que debe ser definido (junto con sus métodos de agregación y remoción de event handlers) en una clase concreta.

3. Glosario

  • Accesors
  • Clase concreta
  • Evento
  • Función de acceso
  • Implementación explícita

4. Literatura & Enlaces

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: Propiedades en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2013/10/propiedades-en-c.html
[3]: lock Statement (C# Reference) - http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx
[4]: Interfaces en C# - Parte 5 | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/05/interfaces-en-c-parte-5.html
[5]: 10.7.2 Event accessors - http://msdn.microsoft.com/en-us/library/aa664456(v=vs.71).aspx
[6]: .NET Matters: Event Accessors - http://msdn.microsoft.com/en-us/magazine/cc163533.aspx
[7]: How to: Implement Custom Event Accessors (C# Programming Guide) - http://msdn.microsoft.com/en-us/library/bb882534.aspx


M

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.