0Pricing
C# Academy · Aula

Padrões de eventos e armadilhas (vazamentos de memória)

Identifique e corrija armadilhas de eventos: cancele a assinatura para evitar vazamentos de memória, armazene referências aos delegados para removê-los e use um padrão de assinatura IDisposable.

Padrões de eventos e armadilhas (vazamentos de memória) é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 3 de 3. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 3 aulas no total.

Visão geral das armadilhas

Objetivo: usar eventos com segurança.

  • Cancele a assinatura para evitar vazamentos de memória
  • Mantenha uma referência ao mesmo manipulador para removê-lo
  • Prefira um pequeno padrão de IDisposable para a limpeza
  • Evite manipuladores anônimos embutidos que não possam ser desconectados

Cancele a assinatura para evitar vazamentos

Os eventos mantêm referências aos assinantes. Se o publicador tiver vida longa e você nunca o desconectar, o assinante não poderá ser coletado.

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
  }
}

Mantenha a referência do manipulador

Para desconectar um manipulador anônimo, armazene-o em uma variável e passe a mesma instância para -=.

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
  }
}

Assinatura descartável

Retorne um IDisposable de Subscribe. Use using para cancelar a assinatura automaticamente.

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
  }
}

Desconexão com try/finally

Use try/finally quando um manipulador precisar ser desconectado mesmo que uma exceção seja lançada.

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
  }
}

Dicas para evitar vazamentos

Dicas:

  • Os assinantes devem gerenciar o próprio cancelamento de assinatura (Dispose, finally ou um método explícito).
  • Evite assinar usando manipuladores anônimos embutidos que não possam ser removidos.
  • Tenha cuidado com eventos estáticos; eles geralmente sobrevivem aos objetos.
  • Mantenha os manipuladores curtos; não bloqueie o publicador.

Causa de vazamentos com eventos

Verificação rápida: qual é uma causa comum de vazamentos de memória ao usar eventos do C#?

Recapitulação

Recapitulação: cancele a assinatura para evitar vazamentos, armazene referências aos manipuladores para removê-los e prefira padrões de limpeza descartáveis ou baseados em finally para garantir tempos de vida seguros dos eventos.

Perguntas Frequentes

A aula “Padrões de eventos e armadilhas (vazamentos de memória)” é grátis?

Sim — o texto completo de “Padrões de eventos e armadilhas (vazamentos de memória)” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 3 aulas no total.

O que vou aprender em “Padrões de eventos e armadilhas (vazamentos de memória)”?

Identifique e corrija armadilhas de eventos: cancele a assinatura para evitar vazamentos de memória, armazene referências aos delegados para removê-los e use um padrão de assinatura IDisposable. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C# Academy?

Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 3.

Quanto tempo leva a aula “Padrões de eventos e armadilhas (vazamentos de memória)”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C# Academy?

Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. delegate, Action/Func, fechamentos
  2. Eventos: publicação/assinatura, palavra-chave event
  3. Padrões de eventos e armadilhas (vazamentos de memória)
← Voltar para C# Academy