Dans l'article, Codage de nouvelles instances d'objets, j'ai écrit sur les différentes façons dont Nouveau des instances d'objets peuvent être créées. Le problème opposé, la suppression d'un objet, est quelque chose dont vous n'aurez pas à vous soucier très souvent dans VB.NET. .NET inclut une technologie appelée Éboueur (GC) qui s'occupe généralement de tout dans les coulisses de manière silencieuse et efficace. Mais parfois, généralement lors de l'utilisation de flux de fichiers, d'objets SQL ou d'objets graphiques (GDI +) (c'est-à-dire, ressources non gérées), vous devrez peut-être prendre le contrôle de l'élimination des objets dans votre propre code.
Tout d'abord, quelques antécédents
Tout comme constructor (le Nouveau mot-clé) crée un nouveau objet, une destructor est une méthode qui est appelée lorsqu'un objet est détruit. Mais il y a un hic. Les personnes qui ont créé .NET ont réalisé que c'était une formule pour les bogues si deux morceaux de code différents pouvaient réellement détruire un objet. Ainsi, le GC .NET est en fait sous contrôle et c'est généralement le seul code qui peut détruire l'instance de l'objet. Le GC détruit un objet quand il le décide et pas avant. Normalement, après qu'un objet quitte la portée, il est
libéré par le Common Language Runtime (CLR). Le GC détruit objets lorsque le CLR a besoin de plus de mémoire libre. Donc, l'essentiel est que vous ne pouvez pas prédire quand GC va réellement détruire l'objet.(Welllll... C'est vrai presque tout le temps. Tu peux appeler GC.Collect et forcer un cycle de collecte des ordures, mais les autorités disent universellement que c'est un mal idée et totalement inutile.)
Par exemple, si votre code a créé un Client objet, il peut sembler que ce code le détruira à nouveau.
Client = Rien
Mais ce n'est pas le cas. (Définir un objet sur Nothing est communément appelé, déréférencement l'objet.) En fait, cela signifie simplement que la variable n'est plus associée à un objet. À un moment donné plus tard, le GC remarquera que l'objet est disponible pour la destruction.
Soit dit en passant, pour les objets gérés, rien de tout cela n'est vraiment nécessaire. Bien qu'un objet comme un bouton propose une méthode Dispose, il n'est pas nécessaire de l'utiliser et peu de gens le font. Les composants Windows Forms, par exemple, sont ajoutés à un objet conteneur nommé Composants. Lorsque vous fermez un formulaire, sa méthode Dispose est appelée automatiquement. Habituellement, vous n'avez à vous soucier de rien de tout cela lorsque vous utilisez des objets non gérés, et même alors juste pour optimiser votre programme.
La façon recommandée de libérer toutes les ressources qui pourraient être détenues par un objet est d'appeler le Disposer méthode pour l'objet (s'il en existe une), puis déréférencer l'objet.
Client. Disposer() Client = Rien
Parce que GC détruira un objet orphelin, que vous définissiez ou non la variable objet sur Nothing, ce n'est pas vraiment nécessaire.
Une autre façon recommandée de s'assurer que les objets sont détruits lorsqu'ils ne sont plus nécessaires est de mettre le code qui utilise un objet dans un En utilisant bloquer. Un bloc Using garantit l'élimination d'une ou plusieurs de ces ressources lorsque votre code est terminé avec elles.
Dans la série GDI +, le En utilisant est utilisé assez fréquemment pour gérer ces objets graphiques embêtants. Par exemple ...
Utilisation de myBrush en tant que LinearGradientBrush _. = Nouveau LinearGradientBrush (_. Moi. ClientRectangle, _. Couleur. Couleur bleue. Rouge, _. LinearGradientMode. Horizontal) <... plus de code ...> Fin de l'utilisation
myBrush est supprimé automatiquement lors de l'exécution de la fin du bloc.
L'approche GC pour gérer la mémoire est un grand changement par rapport à la façon dont VB6 l'a fait. Les objets COM (utilisés par VB6) ont été détruits lorsqu'un compteur de références interne a atteint zéro. Mais il était trop facile de se tromper donc le compteur interne était éteint. (Parce que la mémoire était bloquée et n'était pas disponible pour d'autres objets lorsque cela s'est produit, cela a été appelé une "fuite de mémoire".) Au lieu de cela, GC vérifie réellement si quelque chose fait référence à un objet et le détruit lorsqu'il n'y en a plus les références. L'approche GC a une bonne histoire dans des langages comme Java et est l'une des grandes améliorations de .NET.
Sur la page suivante, nous examinons l'interface IDisposable... l'interface à utiliser lorsque vous devez éliminer des objets non gérés dans votre propre code.
Si vous codez votre propre objet qui utilise des ressources non managées, vous devez utiliser le IDisposable interface pour l'objet. Microsoft vous facilite la tâche en incluant un extrait de code qui crée le modèle qui vous convient.
Cliquez ici pour afficher l'illustration
Cliquez sur le bouton Retour de votre navigateur pour revenir
Le code ajouté ressemble à ceci (VB.NET 2008):
Classe ResourceClass. Implémente IDisposable. 'Pour détecter les appels redondants. Privé disposé comme booléen = faux. 'IDisposable. Sub Dispose Overridable protégé (_. ByVal éliminant comme booléen) sinon pas moi alors disposé. Si vous disposez alors. 'Libre autre état (objets gérés). Fin si. 'Libérez votre propre état (objets non gérés). 'Définissez les grands champs sur null. Fin si. Me.disposed = True. End Sub. #Region "IDisposable Support" 'Ce code ajouté par Visual Basic à. 'mettre correctement en œuvre le modèle jetable. Public Sub Dispose () Implémente IDisposable. Disposer. 'Ne changez pas ce code. 'Mettez le code de nettoyage dedans. 'Dispose (ByVal disposing As Boolean) ci-dessus. Dispose (True) GC.SuppressFinalize (Me) End Sub. Protected Overrides Sub Finalize () 'Ne modifiez pas ce code. 'Mettez le code de nettoyage dedans. 'Dispose (ByVal disposing As Boolean) ci-dessus. Éliminer (faux) MyBase. Finalize () End Sub. #End Region. Fin de classe
Disposer est presque un modèle de conception de développeur «appliqué» dans .NET. Il n'y a vraiment qu'une seule façon correcte de le faire et c'est tout. Vous pourriez penser que ce code fait quelque chose de magique. Ce n'est pas le cas.
Notez d'abord que le drapeau interne disposé court-circuite tout simplement le tout pour que vous puissiez appeler Éliminer (éliminer) aussi souvent que vous le souhaitez.
Le code ...
GC.SuppressFinalize (Me)
... rend votre code plus efficace en indiquant au GC que l'objet a déjà été éliminé (une opération «coûteuse» en termes de cycles d'exécution). Finalize est protégé car GC l'appelle automatiquement lorsqu'un objet est détruit. Vous ne devez jamais appeler Finalize. Le booléen disposer indique au code si votre code a initié l'élimination de l'objet (Vrai) ou si le GC l'a fait (dans le cadre de la Finaliser sous. Notez que le seul code qui utilise le booléen disposer est:
Si vous disposez alors. 'Libre autre état (objets gérés). Fin si
Lorsque vous disposez d'un objet, toutes ses ressources doivent être éliminées. Quand le CLR Éboueur supprime un objet, seules les ressources non gérées doivent être supprimées car le garbage collector prend automatiquement en charge les ressources gérées.
L'idée derrière cet extrait de code est que vous ajoutez du code pour prendre soin des objets gérés et non gérés dans les emplacements indiqués.
Lorsque vous dérivez une classe d'un classe de base qui implémente IDisposable, vous n'avez à remplacer aucune des méthodes de base, sauf si vous utilisez d'autres ressources qui doivent également être supprimées. Si cela se produit, la classe dérivée doit remplacer la méthode Dispose (disposing) de la classe de base pour disposer des ressources de la classe dérivée. Mais n'oubliez pas d'appeler la méthode Dispose (disposing) de la classe de base.
Protected Overrides Sub Dispose (ByVal disposing As Boolean) If Not Me.disposed Then. Si vous disposez alors. 'Ajoutez votre code aux ressources gérées gratuites. Fin si. 'Ajoutez votre code pour libérer des ressources non gérées. Fin si. MyBase. Éliminer (éliminer) End Sub
Le sujet peut être légèrement écrasant. Le but de l'explication ici est de "démystifier" ce qui se passe réellement parce que la plupart des informations que vous pouvez trouver ne vous le disent pas!