La importancia de los eventos

Desde hace tiempo vengo defendiendo que los entornos de desarrollo desde hace tiempo han introducido el concepto de la  POP: Programación Orientada al Punto. Aunque pocos comparten este concepto, lo que sí comparten es que esto del intellisense ha sido y será una maravilla.

Pero todos sabemos que no existen las balas de plata. Y muestra de ello son los eventos a los que tantos estamos acostumbrados y cómo interactúa con el recolector de basura (GC).

Vamos a verlo con un pequeño ejemplo:

Emisor emi = new Emisor();
Receptor recep= new Receptor();

recep.SomeEvent += emi.EventHandler;
recep.DoWork();

emi = null;
// Force collection
GC.Collect();
GC.WaitForPendingFinalizers();
Este código está simplemente creando dos objetos, un emisor y un receptor, hacieno que el receptor se suscriba a un evento del objeto emisor.

Si la clase Emisor tuviese un finalizador y ponemos un punto de interrupción en él, veríamos que nunca se pararía en ese punto haciendo que el objeto liberase todos sus recuros. ¿Qué está pasando entonces? ¿Porqué no se destruye el objeto emisor si claramente se está igualando a null?

Resulta que debido a la subscripción del receptor el objeto emi sigue teniendo una referencia activa por lo que el recolector de basura no puede eliminarlo

De manera que para corregir este comportamiento debemos añadir la siguiente linea a nuestro código:

Emisor emi = new Emisor();
Receptor recep= new Receptor();recep.SomeEvent += emi.EventHandler;
recep.DoWork();
recep.SomeEvent -= emi.EventHandler
emi = null;
GC.Collect();
GC.WaitForPendingFinalizers();

Este código de ejemplo es simple y obvio. Pero en situaciones un poco más complejas y evitar este tipo de cosas (el consumo de memoria empieza a crecer ya que no se libera) debemos asegurarnos de implementar la interfaz IDisposable y encapsular los += y -=.

Espero que os sirva.

Juan María Laó Ramos.