C# comment implémenter la méthode dispose
J'ai besoin de quelques conseils sur la mise en œuvre de la Dispose
méthode.
Dans notre application, l'utilisateur conçoit leur propre INTERFACE utilisateur. J'ai une fenêtre d'aperçu qui montre ce que l'INTERFACE utilisateur va ressembler. Tous les objets dessinés dans cette INTERFACE, finalement, dérivent d'une classe de base commune ScreenObject. Mon aperçu du gestionnaire de contenir un objet unique référence à un ScreenGrid qui est l'objet de la grille pour l'ensemble de la zone d'aperçu.
Question #1
Certains de mes dérivé classes d'écran tenir sur des ressources non managées, comme une connexion de base de données, image bitmap et un WebBrowser
de contrôle. Ces classes ont besoin de disposer de ces objets. J'ai créé un virtual Dispose
méthode dans la base ScreenObject
de la classe de base et de mettre en œuvre un remplacement Dispose
méthode dans chacune des classes dérivées qui détiennent sur des ressources non managées. Cependant, pour l'instant, je viens de créer une méthode appelée Dispose
, je ne suis pas la mise en œuvre de IDisposable
. Dois-je mettre en œuvre IDisposable
? Si oui, comment dois-je mettre en œuvre?
- Seulement sur les classes dérivées qui ont des ressources non managées
- La classe de base et les classes dérivées qui ont des ressources non managées OU
- La classe de base et de toutes les classes dérivées, y compris ceux qui n'ont pas les ressources non managées
Est-il de mal à mettre un virtuel Dispose
méthode dans une classe de base qui n'ont pas les ressources non managées, de sorte que vous pouvez prendre avantage de polymorphisme?
Question #2
À la lecture de la Dispose
méthode et la IDisposable
interface Microsoft indique que l'élimination de l'objet ne doit appeler la Dispose
méthode pour son parent. Le parent doit l'appeler par son parent et ainsi de suite. Pour moi, cela semble en arrière. Je peux avoir envie de se débarrasser d'un enfant, mais de garder son parent autour de.
Je pense qu'elle devrait être dans l'autre sens, un objet en cours de cession doit disposer de ses enfants. Les enfants doivent alors disposer de leurs enfants et ainsi de suite.
Je suis mal ici ou ai-je raté quelque chose?
- Pour votre deuxième question. Peut-être que vous avez mal compris quelque chose. Microsoft ne dit que la classe devrait appeler sa classe parent méthode dispose, ce qui signifie que la méthode de la classe de base. Je suis d'accord que la classe seulement se débarrasser de ses enfants et à la fin de sa base.
- Avez-vous les ressources non managées dans votre classe? Ou avez-vous juste propre à une classe qui détient à son tour les ressources non managées? J'espère que c'est la deuxième, sinon vous aurez à traiter avec des choses amusantes comme la critique de finalisation.
- Question #1: Vous devez mettre en œuvre IDisposable de sorte que vous (et d'autres) peut alors utiliser la
using
déclaration en C#. Avoir une méthode dispose sans la mise en œuvre de IDisposable n'a pas vraiment de sens, vous pourriez juste l'appeler MyCleanUp ainsi. - Votre classe ScreenObject pourrait également avoir un résumé méthode MyCleanUp à la force de sa mise en œuvre. Avec une bonne documentation, il devrait être clair que implementators avez à faire.
- Cela pourrait bien être le 100e double de cette question. Avez-vous la peine, même en regardant la liste des questions similaires?
- Oui je vois beaucoup de les mêmes réponses à la même question, mais j'ai expressément demandé à des questions différentes. Comme dans la mise en œuvre lorsque vous traitez avec de la classe dérivée qui détiennent les ressources non managées et mon interprétation erronée de l'appel de jeter sur l'objet parent, pas de la classe parent.
- Je pensais exactement, pourquoi ne pas simplement créer une méthode comme MyCleanUp. Comme pour le rendre abstrait, qui ne fonctionne pas comme j'ai beaucoup de classes dérivées sans ressources gérées qui n'ont pas à effectuer le nettoyage. Si j'en œuvre IDisposable ce que toutes les classes doivent implémenter la classe de base, et mes classes dérivées qui détiennent sur des ressources non managées seulement?
- L'implémentation de référence sur MSDN n'répondre à l'héritage et tout le reste. Ne pas DIY ici.
- Le but de IDisposable n'est pas pour détruire les objets--c'est pour s'assurer qu'ils peuvent être en toute sécurité abandonné. Sauf quand il serait absolument impossible de le faire, chaque objet doit être conçu de sorte qu'il peut être abandonné en toute sécurité si (1) IDisposable.Disposer est appelé en premier, ou (2) il n'est pas de mettre en œuvre IDisposable. Une classe nécessite de nettoyage personnalisés mais ne pas mettre en œuvre IDisposable ne remplit pas l'une des ci-dessus.
- double possible de Sera le Garbage Collector appel IDisposable.Disposer de moi?
Vous devez vous connecter pour publier un commentaire.
Question 1: mettre en Œuvre
IDisposable
ainsi, selon le modèle suivant:Question 2: est-Ce que Microsoft signifie qu'une classe dérivée appelle dispose sur sa classe parent. Le propriétaire de l'instance uniquement les appels Jeter sur la plupart des dérivés de type.
Un (raccourcie) exemple:
Le propriétaire seuls les appels
Dispose
sur l'Enfant, mais pas sur le Parent. L'Enfant est responsable de l'appelDispose
sur le Parent.base.Dispose(disposing)
dans la classe Enfant à l'extérieur de laif (disposing)
bloc logique que la classe Parent contient des ressources non managées et que le bloc est réservé pour libérer les ressources gérées. SiDispose(false)
est appelée sur l'Enfant, étant donné le contexte actuel de mise en œuvre - les ressources non managées que la société Mère détient ne sera pas libéré.Question 1:
Sur la base des types d'objets de la liste (c'est à dire de la Base de données, WebBrowser, Bitmap, etc.) ce ne sont que des géré ressources .NET est concerné. Ainsi, vous devez mettre en œuvre
IDisposable
sur toute la classe qui a jetables types de membres. S'ils sont déclarés localement cas, il vous suffit d'appeler 'l'aide de ()" sur eux. Bien que ces situations que vous mentionnez n'ont les ressources non managées, sous eux, c'est abstrait, loin de vous par .NET à travers les types que vous utilisez. Depuis que vous utilisez uniquement les types gérés, vous devez mettre en œuvreIDisposable
mais sans un finaliseur. Vous avez seulement besoin de mettre en œuvre un finaliseur si vous avez vraiment des ressources non managées en tant que membres de la classe.Question 2:
Il semble que vous confondez l'héritage (est un) avec l'agrégation/confinement (a une). Par exemple, si "Conteneur" contient une seule ressource en tant que membre de la classe, il est appelé agrégation/confinement. Ainsi, l'appel de
base.Dispose()
dans leIDisposable
mise en œuvre de Conteneur n'a rien à voir avec l'élimination de l'jetables ressources à l'intérieur de de Conteneur. Vous devez vous rappeler que si une classe dérive de Conteneur, dire "DerivedContainer", qu'il est une instance du Conteneur, mais avec d'autres membres et/ou les fonctionnalités. De sorte que toute instance de "DerivedContainer" a tous les membres de sa classe de base "Conteneur" ne. Si vous n'avez jamais appelébase.Dispose()
, le jetable ressource "Conteneur" ne serait pas libéré correctement (il serait effectivement par le GC, mais c'est une mauvaise pratique pour de nombreuses raisons, à juste " de laisser .NET prendre soin d'elle') - veuillez vous référer à mon posté réponse à Est-ce une mauvaise pratique de dépend du .NET automatisé garbage collector?.Si vous n'avez pas d'appel de la classe de base
Dispose()
, vous finirais avec un partiellement éliminés objet (disposé dans la classe dérivée, mais pas dans la classe de base) - un très mauvais scénario. Il est donc très important d'appeler la classe de baseDispose()
.J'ai de bonnes pratiques modèle que j'ai développé (avec beaucoup d'expérience et de débogage des vidages de mémoire) écrit sur mon blog comme un exemple. Il montre comment mettre en œuvre
IDisposable
sur une classe de base ainsi que d'une classe dérivée:http://dave-black.blogspot.com/2011/03/how-do-you-properly-implement.html