0Pricing
C# Academy · Leçon

Modèles d’événements et pièges (fuites mémoire)

Repérez et corrigez les pièges liés aux événements : désabonnez-vous pour éviter les fuites mémoire, conservez les références aux délégués pour pouvoir les supprimer et utilisez un modèle d’abonnement IDisposable.

Modèles d’événements et pièges (fuites mémoire) est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 3. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 3 leçons au total.

Présentation des pièges

Objectif : utiliser les événements en toute sécurité.

  • Désabonnez-vous pour éviter les fuites de mémoire
  • Conservez une référence vers le même gestionnaire pour le supprimer
  • Préférez un petit modèle IDisposable pour le nettoyage
  • Évitez les gestionnaires anonymes en ligne que vous ne pouvez pas détacher

Se désabonner pour éviter les fuites

Les événements conservent des références vers les abonnés. Si le producteur vit longtemps et que vous ne vous en détachez jamais, l’abonné ne peut pas être récupéré.

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

Conserver la référence du gestionnaire

Pour détacher un gestionnaire anonyme, stockez-le dans une variable et transmettez la même instance à -=.

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

Abonnement avec IDisposable

Renvoyez un IDisposable depuis Subscribe. Utilisez using pour vous désabonner automatiquement.

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

Détachement avec try/finally

Utilisez try/finally lorsqu’un gestionnaire doit être détaché même si une exception est levée.

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

Conseils pour éviter les fuites

Conseils :

  • Les abonnés doivent assumer leur désabonnement (Dispose, finally ou méthode explicite).
  • Évitez de vous abonner avec des gestionnaires anonymes en ligne que vous ne pouvez pas supprimer.
  • Soyez prudent avec les événements statiques ; ils survivent souvent aux objets.
  • Gardez les gestionnaires courts ; ne bloquez pas le producteur.

Cause des fuites liées aux événements

Vérification rapide : quelle est une cause courante des fuites de mémoire lors de l’utilisation des événements C# ?

Récapitulatif

Récapitulatif : désabonnez-vous pour éviter les fuites, conservez les références des gestionnaires pour les supprimer et préférez des modèles de nettoyage fondés sur la libération des ressources ou sur finally afin de gérer les durées de vie des événements en toute sécurité.

Questions Fréquemment Posées

La leçon « Modèles d’événements et pièges (fuites mémoire) » est-elle gratuite ?

Oui — le texte complet de « Modèles d’événements et pièges (fuites mémoire) » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 3 leçons au total.

Qu'est-ce que j'apprendrai dans « Modèles d’événements et pièges (fuites mémoire) » ?

Repérez et corrigez les pièges liés aux événements : désabonnez-vous pour éviter les fuites mémoire, conservez les références aux délégués pour pouvoir les supprimer et utilisez un modèle d’abonnemen… Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer C# Academy ?

Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 3.

Combien de temps prend la leçon « Modèles d’événements et pièges (fuites mémoire) » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?

Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. delegate, Action/Func et fermetures
  2. Événements : publication/abonnement, mot-clé event
  3. Modèles d’événements et pièges (fuites mémoire)
← Retour à C# Academy