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 inverse, disposer 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 comme constructor (le Nouveau ) crée un nouvel objet, un 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.
Mais ce n'est pas le cas. (La définition d'un objet sur Nothing est communément appelée, 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.
Customer.Dispose () Customer = Nothing
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 (_ Me.ClientRectangle, _ Color.Blue, Color.Red, _ LinearGradientMode.Horizontal) Fin de l'utilisation
myBrush est éliminé automatiquement lorsque la fin du bloc est exécutée.
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, le GC vérifie réellement si quelque chose fait référence à un objet et le détruit lorsqu'il n'y a plus de 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 Private supprimé comme booléen = False' IDisposable Protected Overridable Sub Dispose (_ ByVal supprimant As Boolean) If Not Me.disposed Then If disposing Then 'Free other state (managed objects). End If 'Libérez votre propre état (objets non gérés). 'Définissez les grands champs sur null. End If Me.disposed = True End Sub #Region "IDisposable Support" 'Ce code ajouté par Visual Basic pour' implémenter correctement le modèle jetable. Public Sub Dispose () Implémente IDisposable.Dispose 'Ne modifiez pas ce code. 'Mettez le code de nettoyage dans' 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 dans' Dispose (ByVal disposing As Boolean) ci-dessus. Dispose (False) MyBase.Finalize () End Sub #End Region End Class
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.
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 supprimez Then 'Free autre état (objets gérés). Fin si
Lorsque vous disposez d'un objet, toutes ses ressources doivent être éliminées. Lorsque le garbage collector CLR supprime un objet, seules les ressources non managé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'une classe de base qui implémente IDisposable, vous n'avez pas à remplacer les 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 If disposing Then 'Ajoutez votre code aux ressources gérées libres. End If 'Ajoutez votre code pour libérer des ressources non gérées. End If MyBase.Dispose (disposing) 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 disent pas!