En Visual Basic, un constructeur est une procédure Sub New, qui est appelée lors de la création d'une instance d'une classe et initialise l'objet. Un destructeur est implémenté à l'aide de la méthode Finalize ou de l'interface IDisposable (méthode Dispose), ce qui est particulièrement important pour libérer des ressources.
Dans le Visual Basic classique, le constructeur était appelé automatiquement lors de la création d'objets (Class_Initialize), le destructeur – lors de la suppression (Class_Terminate). Dans VB.NET, des constructeurs surchargés ont été ajoutés, délimitant la libération des ressources gérées et non gérées, et l'utilisation du ramasse-miettes (GC).
Une utilisation incorrecte des constructeurs ou des destructeurs conduit à des fuites de mémoire, à une mauvaise initialisation des objets ou à des blocages de ressources (par exemple, des fichiers).
Utilisez Sub New pour initialiser des objets, implémentez toujours Dispose pour libérer explicitement des ressources. Si un destructeur (Finalize) est utilisé, gardez à l'esprit la latence du GC et l'impossibilité de prévoir le moment de son appel.
Exemple de code :
Public Class ResourceHolder Implements IDisposable Private resource As SomeResource Public Sub New() resource = New SomeResource() Console.WriteLine("Ressource allouée") End Sub Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overridable Sub Dispose(disposing As Boolean) If disposing Then If resource IsNot Nothing Then resource.Release() resource = Nothing End If End If End Sub End Class
Caractéristiques clés :
Peut-on appeler manuellement le constructeur Sub New d'un objet déjà existant ?
Non, le constructeur est appelé seulement lors de la création d'un objet. Pour réinitialiser, utilisez une méthode distincte Reset ou similaire.
Quand Finalize est-il appelé et est-il toujours garanti ?
Finalize est appelé par le ramasse-miettes lors de la destruction de l'objet, mais son exécution n'est pas garantie (par exemple, en cas de terminaison anormale du processus ou de coupure de courant).
Pourquoi faut-il appeler GC.SuppressFinalize à l'intérieur de Dispose ?
Cela empêche l'appel répété de Finalize pour un objet déjà libéré manuellement, améliorant les performances et évitant les fuites de mémoire.
Dans le projet, Dispose n'a pas été implémenté, et plusieurs fichiers restaient bloqués après la fin de l'application - les ressources n'étaient pas libérées jusqu'à ce que le ramasse-miettes n'intervienne.
Avantages :
Inconvénients :
Implémentation d'IDisposable et de Dispose, utilisation de Using lors du travail avec des ressources externes. Tous les fichiers se ferment correctement et l'application fonctionne de manière stable.
Avantages :
Inconvénients :