Вы находитесь на странице: 1из 11

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

Delegates y eventos
Delegates
Un delegate es muy similar a un puntero a funcin de C++, es una estructura de datos
que referencia a un mtodo esttico o a un mtodo de instancia de un objeto.
Existen algunas diferencias:
- Un puntero a funcin de C++ slo puede referenciar funciones estticas.
- Un delegate no slo referencia al punto de entrada del mtodo, sino tambin a la
instancia del objeto al que pertenece el mtodo.
El sentido de los delegates es permitir que un mtodo pueda recibir como parmetro un
puntero a otro mtodo. Es ms, no es necesario conocer en tiempo de compilacin el
mtodo concreto que se pasa como parmetro: puede asignarse en tiempo de ejecucin,
lo cual ofrece una gran flexibilidad a la hora de programar.
El tipo base de todos los delegates es la clase System.Delegate,que quiere decir que un
delegate es una instancia de la clase System.Delegate (o una derivada).
Los delegates no necesitan saber la clase de objeto al cual referencian. Lo que necesitan
saber es la definicin del mtodo al que referencian.

Declaracin de Delegates.
Una declaracin de un delegate define un tipo de referencia que extiende la clase
System.Delegate y que puede utilizarse para encapsular un mtodo con una definicin
determinada..
La sintaxis de la declaracin es:
declaracin-delegate:
atributosopc
modificadores-del-delegateopc
delegate
identificador(lista-parmetros-formalesopc ) ;
modificadores-del-delegate:
modificador-del-delegate
modificadores-del-delegate modificador-del-delegate
modificador-del-delegate:
new
public
protected
internal
private

Por ejemplo:
delegate int MiDelegate();

Un ejemplo ms detallado es el siguiente:


delegate int MiDelegate(int x);

1/11

tipo-resultado

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

class MiClase
{
MiDelegate d = new MiDelegate(Cuadrado);
static float Cuadrado(float x) {
return x * x;
}
static int Cuadrado(int x) {
return x * x;
}
}

Utilizacin de Delegates.
Una instancia de tipo delegate encapsula un mtodo, tambin llamado entidad
invocable. En el caso de mtodos estticos, una entidad invocable consta nicamente
del mtodo. En el caso de mtodos de instancia, una entidad invocable consta de una
instancia de la clase del mtodo y un mtodo de tal instancia.
Un ejemplo de utilizacin de instancias de tipo delegate es:
using System;
// declaracin del delegate
delegate int MiDelegate();
public class MiClase
{
public int MetodoInstancia ()
{
Console.WriteLine("Hola desde el mtodo de instancia.");
return 0;
}
static public int MetodoEstatico ()
{
Console.WriteLine("Hola desde el mtodo esttico.");
return 0;
}
}
public class Aplicacion
{
static void Main (string[] args)
{
MiClase p = new MiClase();
// Asociar el delegate al mtodo de instancia:
MiDelegate d = new MiDelegate(p.MetodoInstancia);
// Invocacin al mtodo de instancia a travs del delegate:
d();
// Asociar el delegate al mtodo esttico:
d = new MiDelegate(MiClase.MetodoEstatico);
// Invocacin al mtodo esttico a travs del delegate:
d();
}
}

2/11

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

La salida de este programa es el de la figura 8.1:

Figura 8.1

Delegates Multicast.
Un delegate de tipo multicast puede asociarse a ms de un mtodo, de modo que
invocando al delegate una sola vez, todos los mtodos a los que est asociado sean
invocados secuencialmente.
Un delegate referencia realmente una lista de mtodos a la que es posible aadir o quitar
mtodos utilizando los operadores +, +=, - y -=.
Para ilustrar esto puede modificarse el mtodo Main() del ejemplo anterior:
static void Main (string[] args)
{
MiClase p = new MiClase();
// Asociar el delegate al mtodo de instancia:
MiDelegate d = new MiDelegate(p.MetodoInstancia);
// Asociar el delegate al mtodo esttico, se utiliza
//el operador + para que se aada el mtodo esttico
//a la lista de mtodos apuntados por el delegate d:
d += new MiDelegate(MiClase.MetodoEstatico);
// Invocacin
//delegate:

de

ambos

d();
}

Obsrvese que slo se invoca una vez el delegate d().


El resultado se representa en la figura 8.2:

3/11

mtodos

travs

del

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

Figura 8.2

Existe una clase especfica para este tipo de delegates multicast llamada
System.MulticastDelegate, la cual deriva de System.Delegate y est en el
assembly Mscorlib (Mscorlib.dll).
La clase Delegate soporta una lista de mtodos siempre que todos devuelvan el mismo
tipo de datos, pero en una lista de varios mtodos esto no tiene porqu ser as. Cuando el
compilador detecta que un delegate devuelve void crea una instancia de
MulticastDelegate en lugar de una de Delegate.

4/11

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

Eventos.
En su sentido ms concreto, un evento es un campo o propiedad de una clase o
estructura. El tipo del evento es delegate, lo cual quiere decir que puede referenciar a
una lista de mtodos.
Lo interesante de los eventos es que son utilizados por la clase a la que pertenecen para
notificar que algo ha sucedido a otras clases.

El modelo de eventos en el entorno .NET


El modelo de eventos .NET se basa en los conceptos de productor o fuente de eventos
y consumidor o manejador de eventos.

Figura 8.3. Modelo de eventos en el entorno .NET


El productor o fuente puede generar uno o varios eventos diferentes. El consumidor o
manejador se suscribe a uno o varios eventos del productor para que se le notifique
cuando un evento suceda.
Para poder implementar el mecanismo de suscripcin a eventos se utilizan los delegates.
El productor tiene tantas instancias de tipo delegate como eventos pueda producir.
Cuando un consumidor quiere suscribirse a un evento concreto ha de aadir a la lista de
mtodos del delegate correspondiente la referencia a un mtodo (del consumidor) que
ser el que se invoque a travs del delegate cuando se de el evento. Al mtodo cuya
referencia se pasa al delegate se llama mtodo manejador del evento.

El productor o fuente del evento.


La clase que se comporta como fuente de eventos se caracteriza por tener un miembro
de tipo event, el cual se construye a partir de un tipo delegate. Este miembro de tipo
event es el que va a referenciar a la lista de mtodos manejadores del evento.
Un ejemplo de clase fuente o productor de eventos puede es:

5/11

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

//Delegate que ser utilizado como tipo base del evento MiRefME
public delegate void ReferenciaManejadoresEventos (object fuente,
ArgumentosEvento eventArgs);
//Clase productora o fuente del evento MiRefME
public class MiFuenteEventos
{
//MiRefME es el evento, su tipo est determinado por el delegate
//ReferenciaManejadoresEventos
public event ReferenciaManejadoresEventos MiRefME;
//Este mtodo ser llamado por los consumidores de eventos
//para suscribirse al evento
public void AadirManejador (MiManejadorEventos manejador)
{
//Aade a la lista de mtodos manejadores la referencia al
//mtodo ManejadorMiFuenteEventos, el cual ha de existir
//en el objeto manejador y ser el mtodo del consumidor
//al que se llame cuando se de el evento MiRefME
this.MiRefME
+=
new
ReferenciaManejadoresEventos
(manejador.ManejadorMiFuenteEventos);
}
//Este mtodo ser llamado cuando se desee lanzar el evento
public void LanzarEvento ()
{
//A travs de MiRefME se invoca a todos los mtodos
//manejadores registrados en la lista referenciada por
//MiRefME.
this.MiRefME
(this,new
ArgumentosEvento
("MiFuenteEventos"));
}
}

El elemento primordial de esta clase es


public event ReferenciaManejadoresEventos MiRefME;

al cual pueden suscribirse los consumidores o manejadores de eventos y a travs del


cual pueden ser invocados. El resto, es decir, los mtodos de la clase, han sido creados
para facilitar el manejo del evento.
Es importante notar que la estructura de los mtodos manejadores, cuyas referencias se
aadirn a la lista de MiRefME, es determinada por el delegate:
public

delegate

void

ReferenciaManejadoresEventos (object fuente,


ArgumentosEvento
eventArgs);

en este ejemplo como puede verse, al invocar a los mtodos manejadores del evento se
le pasan dos argumentos (que es el caso ms comn):
fuente
representa la clase del objeto que ha generado el evento.
eventArgs
representa los argumentos del evento.

6/11

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

Los argumentos del evento.


Cuando se notifica un evento a un consumidor, se transmite al consumidor o manejador
cierta informacin relativa al evento. Piense en un evento pulsacin de tecla que se
notifique a un formulario. Un dato interesante es el cdigo de la tecla pulsada. A esta
informacin relativa al evento se le llama argumentos del evento y lo normal es que sea
un objeto de una clase derivada de la clase System.EventArgs.
Siguiendo el ejemplo anterior:
//Al notificar que ha sucedido un evento, lo ms comn
//es que se desee dar alguna informacin ms.
//Esto puede hacerse utilizando una clase derivada de EventArgs
//en la que se indiquen los argumentos del evento.
public class ArgumentosEvento : EventArgs
{
public string fuenteEvento;
public ArgumentosEvento (string fuenteEvento)
{
this.fuenteEvento = fuenteEvento;
}
}

El consumidor del evento.


El consumidor del evento es un objeto al que se le avisa o notifica que el evento ha
ocurrido. Dicho objeto realiza una accin de respuesta a ese evento (por ejemplo, la
clase Formulario puede querer ser avisada de un evento pulsacin de tecla para mostrar
el cdigo de la tecla en una caja de texto).
Para poder realizar la accin de respuesta, la clase consumidora del evento ha de poseer
un mtodo que ser invocado cuando se de el evento y cuyo cdigo provocar la
respuesta. Siguiendo con el ejemplo anterior, la clase consumidora o manejadora puede
ser:
//Una clase manejadora del evento MiRefME ha de disponer del mtodo
//ManejadorMiFuenteEventos
public class MiManejadorEventos
{
public void ManejadorMiFuenteEventos (object fuente,
ArgumentosEvento eventArgs)
{
System.Console .WriteLine ("Se ha lanzado un evento");
System.Console.WriteLine
("El
origen
es:
"
+
eventArgs.fuenteEvento);
}
}

El mtodo ManejadorMiFuenteEventos es el que deber ser invocado cuando se d el


evento. Para ello ha de estar referenciado por la lista del evento MiRefME (obsrvese que
los
argumentos
que
espera
son
los
que
indica
el
delegate
ReferenciaManejadoresEventos.

7/11

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

Suscripcin al evento.
Una vez se dispone de las clases productora o fuente y consumidora o manejadora es
posible crear objetos de ambas y conectarlos entre s. Al mecanismo de conexin entre
manejador y fuente se le llama suscripcin y consiste en aadir la referencia al
mtodo manejador del evento a la lista de referencias del evento (MiRefME).
Siguiendo con el ejemplo anterior:
public class Aplicacion {
public static void Main(string [] args)
{
MiFuenteEventos MFE = new MiFuenteEventos ();
MiManejadorEventos MME = new MiManejadorEventos ();
//Suscripcin al evento
MFE.AadirManejador (MME);
...
...

Al pasarle la referencia al objeto MME (MiManejadorEventos) al mtodo


AadirManejador de la fuente de eventos, se aade la referencia al mtodo
ManejadorMiFuenteEventos en la lista de manejadores del evento.
A partir de ahora, cada vez que se de el evento MiRefME, se llamar al mtodo
ManejadorMiFuenteEventos del objeto MME.
Es importante tener en cuenta que el modelo de eventos es un patrn de comportamiento
que se ha diseado para manejar la interaccin del usuario con el sistema en las
aplicaciones grficas (aunque no es su nica aplicacin).
De este modo puede comprenderse que un caso ejemplo es que un objeto Formulario
desee suscribir un mtodo OnClick() al evento click de un objeto de la clase Button.
As, cuando el usuario pulse el objeto de la clase Button se dar el evento click y se
llamar al mtodo OnClick() del objeto Formulario.

Lanzamiento del evento.


Cuando ocurre el evento ha de invocarse a todos los mtodos manejadores suscritos al
evento. En el caso de una aplicacin grfica esta situacin puede corresponder a una
pulsacin con el ratn por parte del usuario sobre un botn. En este caso, el S.O. es el
encargado de lanzar el evento, es decir, llamar al mtodo OnClick() del objeto
Formulario suscrito al evento click sobre el botn.
En el ejemplo que se est siguiendo un modo de lanzar el evento es:
MFE.LanzarEvento ();

Con lo que la clase aplicacin puede quedar como sigue:


public class Aplicacion {
public static void Main(string [] args)
{
MiFuenteEventos MFE = new MiFuenteEventos ();
MiManejadorEventos MME = new MiManejadorEventos ();
//Suscripcin al evento

8/11

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

MFE.AadirManejador (MME);
System.Console.WriteLine ("Si desea lanzar el evento pulse
Enter");
System.Console.ReadLine();
//Lanzamiento del evento
MFE.LanzarEvento ();
}
}

En este caso el evento es lanzado explcitamente cuando el usuario pulsa ENTER.

El ejemplo completo.
El resultado de unir el cdigo comentado es:
using System;
//Al notificar que ha sucedido un evento, lo ms comn
//es que se desee dar alguna informacin ms.
//Esto puede hacerse utilizando una clase derivada de EventArgs
//en la que se indiquen los argumentos del evento.
public class ArgumentosEvento : EventArgs
{
public string fuenteEvento;
public ArgumentosEvento (string fuenteEvento)
{
this.fuenteEvento = fuenteEvento;
}
}
//Delegate que ser utilizado como tipo base del evento MiRefME
public delegate void ReferenciaManejadoresEventos (object fuente,
ArgumentosEvento eventArgs);
//Clase productora o fuente del evento MiRefME
public class MiFuenteEventos
{
//MiRefME es el evento, su tipo est determinado por el delegate
//ReferenciaManejadoresEventos
public event ReferenciaManejadoresEventos MiRefME;
//Este mtodo ser llamado por los consumidores de eventos
//para suscribirse al evento
public void AadirManejador (MiManejadorEventos manejador)
{
//Aade a la lista de mtodos manejadores la referencia al
//mtodo ManejadorMiFuenteEventos, el cual ha de existir
//en el objeto manejador y ser el mtodo del consumidor
//al que se llame cuando se de el evento MiRefME
this.MiRefME
+=
new
ReferenciaManejadoresEventos
(manejador.ManejadorMiFuenteEventos);
}
//Este mtodo ser llamado cuando se desee lanzar el evento
public void LanzarEvento ()
{

9/11

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

//A travs de MiRefME se invoca a todos los mtodos


//manejadores registrados en la lista referenciada por
//MiRefME.
this.MiRefME
(this,new
ArgumentosEvento
("MiFuenteEventos"));
}
}
//Una clase manejadora del evento MiRefME ha de disponer del mtodo
//ManejadorMiFuenteEventos
public class MiManejadorEventos
{
public void ManejadorMiFuenteEventos (object fuente,
ArgumentosEvento eventArgs)
{
System.Console .WriteLine ("Se ha lanzado un evento");
System.Console.WriteLine ("El origen es: " +
eventArgs.fuenteEvento);
}
}
public class Aplicacion {
public static void Main(string [] args)
{
MiFuenteEventos MFE = new MiFuenteEventos ();
MiManejadorEventos MME = new MiManejadorEventos ();
//Suscripcin al evento
MFE.AadirManejador (MME);
System.Console.WriteLine ("Si desea lanzar el evento pulse
Enter");
System.Console.ReadLine();
//Lanzamiento del evento
MFE.LanzarEvento ();
}
}

Al ejecutarlo se mostrar la siguiente pantalla:

Figura 8.4
10/11

Marco Besteiro y Miguel Rodrguez

Delegates y Eventos

Si se pulsa la tecla ENTER se lanzar el evento:

Figura 8.5

11/11

Вам также может понравиться