0Pricing
C# Academy · Lección

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

Comprobación rápida: ¿Cuál es una causa habitual de fugas de memoria al usar eventos de C#?

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

  1. delegate, Action/Func y cierres
  2. Eventos: publicación/suscripción y palabra clave event
  3. Patrones de eventos y errores comunes (fugas de memoria)
← Volver a C# Academy