En Visual Basic, l'implémentation de l'interface IDisposable (motif Dispose) permet de libérer correctement les ressources (par exemple, les fichiers, les connexions à la base de données, les objets graphiques), qui ne sont pas gérées par le ramasse-miettes.
Une implémentation typique est la suivante :
Public Class FileManager Implements IDisposable Private fileStream As FileStream Private disposed As Boolean = False Public Sub New(path As String) fileStream = New FileStream(path, FileMode.Open) End Sub Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overridable Sub Dispose(disposing As Boolean) If Not disposed Then If disposing AndAlso fileStream IsNot Nothing Then fileStream.Dispose() End If disposed = True End If End Sub Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub End Class
Important : Utilisez la structure Using ... End Using — cela garantit l'appel automatique de Dispose :
Using manager As New FileManager("data.txt") ' opérations avec le fichier End Using
Subtilités :
Question : "Pourquoi est-il nécessaire d'appeler GC.SuppressFinalize(Me) dans la méthode Dispose ?"
Réponse correcte : Cela informe le ramasse-miettes qu'il n'est pas nécessaire d'appeler le finaliseur (Finalizer), car les ressources ont déjà été nettoyées manuellement via Dispose. Sans cela, le finaliseur s'exécutera inutilement, ce qui réduira les performances et peut entraîner un nettoyage en double.
Histoire
Dans un logiciel bancaire, IDisposable a été mal implémenté — ils ont oublié d'appeler Dispose sur la base de données, ce qui a entraîné des fuites de connexions. En moyenne, l'application "gelait" après 2–3 jours de fonctionnement continu.
Histoire
Dans un service médical, Dispose a été mal implémenté (missing "disposed" flag). La méthode Dispose était appelée plusieurs fois de suite, ce qui entraînait des tentatives de libération répétée d'une même ressource et provoquait des exceptions.
Histoire
Dans un éditeur graphique, ils ont oublié d'appeler GC.SuppressFinalize(Me). Le finaliseur s'exécutait même après Dispose, entraînant un double nettoyage des ressources et une instabilité (violation d'accès).