Ce cours explique clairement quand et pourquoi utiliser Dispose(), comment le combiner avec
le mot‑clé using, comment éviter les fuites mémoire liées aux événements, et comment cela interagit ou
non avec Task.Run() et l’asynchronisme en C#.
Dispose() sert à libérer des ressources non gérées par le garbage collector.
Ces ressources incluent entre autres :
Règle d’or : si une classe implémente IDisposable → appelle Dispose.
using var stream = File.OpenRead("data.txt");
using var img = Image.FromFile("photo.png");
// Dispose() sera appelé automatiquement à la fin du scope
using (var connection = new SqlConnection(cs))
{
connection.Open();
}
// Dispose() appelé ici automatiquement
Équivalent généré par le compilateur :
var connection = new SqlConnection(cs);
try
{
connection.Open();
}
finally
{
connection.Dispose();
}
Cette erreur est très fréquente. Beaucoup pensent que await Task.Run(...) déclenche Dispose.
C'est faux.
using var cnn = new Cnn();
await Task.Run(() =>
{
cnn.Run(progress, token);
});
// Ici Dispose() est appelé automatiquement
var cnn = new Cnn();
await Task.Run(() => cnn.Run(progress, token));
// ❌ cnn.Dispose() n'est jamais appelé → fuite potentielle
En C#, les événements causent facilement des fuites mémoire car le publisher garde une référence forte vers l’abonné.
publisher.Changed += OnChanged; // peut empêcher le GC de collecter l'objet
public class Listener : IDisposable
{
private readonly Publisher _publisher;
public Listener(Publisher publisher)
{
_publisher = publisher;
_publisher.Changed += OnChanged;
}
private void OnChanged(object? sender, EventArgs e)
{
// ...
}
public void Dispose()
{
_publisher.Changed -= OnChanged;
}
}
using var listener = new Listener(publisher);
Grâce à Dispose(), l'abonnement est supprimé automatiquement → fuite évitée.
public class Engine : IDisposable
{
private readonly FileStream _log;
private readonly SqlConnection _db;
private readonly CancellationTokenSource _cts = new();
private readonly Publisher _publisher;
public Engine(Publisher publisher)
{
_log = File.OpenWrite("log.txt");
_db = new SqlConnection("...");
_publisher = publisher;
_publisher.Changed += OnChanged;
}
public async Task RunAsync()
{
await _db.OpenAsync();
await _log.WriteAsync(...);
}
private void OnChanged(object? s, EventArgs e)
{
// ...
}
public void Dispose()
{
_publisher.Changed -= OnChanged;
_log.Dispose();
_db.Dispose();
_cts.Dispose();
}
}
using var engine = new Engine(publisher);
await engine.RunAsync();
IDisposableSi tu veux, je peux aussi générer :
Dis‑moi simplement ce que tu veux !