Patrones de eventos y errores comunes (fugas de memoria)
Detecte y corrija errores comunes de los eventos: quite la suscripción para evitar fugas de memoria, conserve referencias a los delegates para poder eliminarlos y use un patrón de suscripción IDisposable.
Patrones de eventos y errores comunes (fugas de memoria) es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 3 de 3. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 3 lecciones en total.
Descripción general de los errores frecuentes
Objetivo: Usar los eventos de forma segura.
- Cancele la suscripción para evitar fugas de memoria
- Conserve una referencia al mismo manejador para eliminarlo
- Prefiera un pequeño patrón IDisposable para la limpieza
- Evite los manejadores anónimos insertados directamente que no pueda desvincular
Cancelar la suscripción para evitar fugas
Los eventos mantienen referencias a los suscriptores. Si el publicador tiene una vida útil larga y nunca se desvincula un suscriptor, este no puede ser recolectado.
using System;
public class Publisher
{
public event EventHandler Tick;
public void Fire()
{
EventHandler h = Tick;
if (h != null) h(this, EventArgs.Empty);
}
}
public class Subscriber
{
public void Handle(object s, EventArgs e)
{
Console.WriteLine("Handling tick");
}
public void Subscribe(Publisher p) { p.Tick += Handle; }
public void Unsubscribe(Publisher p) { p.Tick -= Handle; } // required to avoid leaks
}
public class Program
{
public static void Main(string[] args)
{
Publisher p = new Publisher();
Subscriber s = new Subscriber();
s.Subscribe(p);
p.Fire(); // prints once
s.Unsubscribe(p); // detach when done
s = null; // now eligible for GC in a real app
p.Fire(); // no output
}
}
Conservar la referencia del manejador
Para desvincular un manejador anónimo, guárdelo en una variable y pase la misma instancia a -=.
using System;
public class Button
{
public event EventHandler Click;
public void Simulate()
{
EventHandler h = Click;
if (h != null) h(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main(string[] args)
{
Button b = new Button();
// BAD: cannot easily remove this later
// b.Click += (s, e) => Console.WriteLine("inline");
// GOOD: store the handler, attach, later detach the same instance
EventHandler saved = (s, e) => Console.WriteLine("saved");
b.Click += saved;
b.Simulate(); // prints "saved"
b.Click -= saved; // can remove because we kept the reference
b.Simulate(); // no output
}
}
Suscripción descartable
Devuelva un IDisposable desde Subscribe. Use using para cancelar automáticamente la suscripción.
using System;
public class Ticker
{
public event EventHandler Tick;
public IDisposable Subscribe(EventHandler handler)
{
Tick += handler;
return new Unsubscriber(this, handler);
}
private sealed class Unsubscriber : IDisposable
{
private Ticker _t;
private EventHandler _h;
private bool _done;
public Unsubscriber(Ticker t, EventHandler h) { _t = t; _h = h; }
public void Dispose()
{
if (!_done)
{
_t.Tick -= _h;
_done = true;
}
}
}
public void Fire()
{
EventHandler h = Tick;
if (h != null) h(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main(string[] args)
{
Ticker t = new Ticker();
using (t.Subscribe((s, e) => Console.WriteLine("tick")))
{
t.Fire(); // prints once
}
t.Fire(); // nothing after disposal
}
}
Desvinculación con try/finally
Use try/finally cuando deba desvincular un manejador incluso si se produce una excepción.
using System;
public class Alarm
{
public event EventHandler Ring;
public void Trigger()
{
EventHandler h = Ring;
if (h != null) h(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main(string[] args)
{
Alarm a = new Alarm();
EventHandler h = (s, e) => Console.WriteLine("ring");
a.Ring += h;
try
{
a.Trigger(); // do work with subscription active
}
finally
{
a.Ring -= h; // always detach
}
a.Trigger(); // no output
}
}
Consejos para evitar fugas
Consejos:
- Los suscriptores deben hacerse cargo de cancelar su suscripción (Dispose, finally o un método explícito).
- Evite suscribirse con manejadores anónimos insertados directamente que no pueda eliminar.
- Tenga cuidado con los eventos estáticos; a menudo sobreviven a los objetos.
- Mantenga los manejadores breves; no bloquee al publicador.
Causa de las fugas con eventos
Repaso
Repaso: Cancele la suscripción para evitar fugas, conserve las referencias de los manejadores para poder eliminarlos y prefiera patrones de limpieza basados en IDisposable o finally para gestionar de forma segura la vida útil de los eventos.
Preguntas frecuentes
¿La lección «Patrones de eventos y errores comunes (fugas de memoria)» es gratis?
Sí — el texto completo de «Patrones de eventos y errores comunes (fugas de memoria)» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 3 lecciones en total.
¿Qué aprenderé en «Patrones de eventos y errores comunes (fugas de memoria)»?
Detecte y corrija errores comunes de los eventos: quite la suscripción para evitar fugas de memoria, conserve referencias a los delegates para poder eliminarlos y use un patrón de suscripción IDispos… Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar C# Academy?
No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 3.
¿Cuánto tiempo toma la lección «Patrones de eventos y errores comunes (fugas de memoria)»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de C# Academy?
Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- delegate, Action/Func y cierres
- Eventos: publicación/suscripción y palabra clave event
- Patrones de eventos y errores comunes (fugas de memoria)