Sera le Garbage Collector appel IDisposable.Jetez-il pour moi?
L' .NET IDisposable Modèle implique que si vous écrivez un finaliseur, et de mettre en œuvre IDisposable, que votre finaliseur besoin d'appeler explicitement la Jeter.
Ce qui est logique, et c'est ce que j'ai toujours fait dans les rares cas où un finaliseur est justifiée.
Cependant, qu'advient-il si je viens de le faire:
class Foo : IDisposable
{
public void Dispose(){ CloseSomeHandle(); }
}
et de ne pas mettre en œuvre un outil de finalisation, ou quoi que ce soit. Va le cadre de l'appel de la méthode dispose pour moi?
Oui je me rends compte que cela paraît stupide, et en toute logique implique qu'il ne sera pas, mais j'ai toujours eu que 2 choses à l'arrière de ma tête qui m'ont fait de doute.
-
Quelqu'un il y a quelques années m'a dit une fois qu'il serait en fait cela, et que cette personne avait une très solide track record "connaître leurs trucs."
-
Le compilateur/cadre de l'autre la "magie" des choses en fonction de ce que les interfaces de vous mettre en œuvre (par exemple: foreach, les méthodes d'extension, la sérialisation basée sur les attributs, etc), il est donc logique que cela pourrait être la "magie" de trop.
Alors que j'ai lu beaucoup de choses sur elle, et il y a eu beaucoup de choses implicites, je n'ai jamais été en mesure de trouver un définitive réponse Oui ou Non à cette question.
Vous devez vous connecter pour publier un commentaire.
L' .Net Garbage Collector appelle l'Objet.Finaliser une méthode d'un objet sur la collecte des ordures. Par par défaut cela ne rien et doit être overidden si vous souhaitez libérer des ressources supplémentaires.
Disposer est PAS appelée automatiquement et doit être explicitement appelé si les ressources doivent être libérés, comme dans une "aide" ou "essayer, enfin," bloc
voir http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx pour plus d'informations
Je tiens à souligner Brian point dans son commentaire, parce que c'est important.
Finaliseurs ne sont pas déterministes destructeurs comme en C++. Comme d'autres l'ont souligné, il n'existe aucune garantie que lorsqu'il sera appelé, et en effet, si vous avez assez de mémoire, si elle jamais être appelé.
Mais la mauvaise chose à propos de finaliseurs, c'est que, comme Brian l'a dit, il provoque votre objet de survivre à la collecte des ordures. Cela peut être mauvais. Pourquoi?
Comme vous pouvez ou ne pouvez pas savoir, la GC est divisé en générations - Gen 0, 1 et 2, ainsi que le Grand Tas d'Objets. Split est un lâche terme - vous obtenir un bloc de mémoire, mais il y a des pointeurs de l'endroit où les Gen 0 objets de début et de fin.
Le processus de la pensée est que vous aurez probablement utiliser beaucoup d'objets qui sera de courte durée. Donc, ceux qui devraient être faciles et rapides pour la GC pour obtenir à la génération 0 objets. Alors, quand il s'agit de la mémoire de la pression, la première chose qu'il fait est un Gen 0 collection.
Maintenant, si cela ne résout pas assez de pression, puis il remonte et fait un Gen 1 balayage (rétablissement de la génération 0), et puis si toujours pas assez, il n'a Gen 2 de balayage (en refaisant la Gen 1 et de la génération 0). Donc, nettoyage à longue durée de vie des objets peut prendre du temps et être plutôt cher (puisque votre fils peut être suspendu pendant l'opération).
Cela signifie que si vous faites quelque chose comme cela:
Votre objet, n'importe quoi, va vivre à la Génération 2. C'est parce que la GC n'a aucun moyen de l'appel de l'outil de finalisation au cours de la collecte des ordures. Afin de voir les objets qui doivent être finalisés sont déplacés vers une file d'attente spéciale pour être nettoyés par un autre thread (thread finaliseur - qui, si vous tuez fait toutes sortes de mauvaises choses se produisent). Cela signifie que vos objets de traîner plus longtemps, et potentiellement une force de plus garbage collections.
Donc, tout ça est juste pour les conduire à la maison le point que vous souhaitez utiliser IDisposable de nettoyer les ressources autant que possible et essayer sérieusement à trouver des façons de contourner à l'aide de l'outil de finalisation. C'est dans votre application à son meilleur intérêt.
Il ya beaucoup de bonnes discussion déjà ici, et je suis un peu en retard à la fête, mais je voulais ajouter quelques points à moi-même.
C'est la version simple, mais il ya beaucoup de nuances qui peuvent vous passionner sur ce modèle.
À mon avis, il est beaucoup mieux d'éviter d'avoir tout les types qui contiennent directement les deux jetable, des références et des ressources autochtones qui peut exiger de finalisation. SafeHandles fournir très propre façon de faire cela par l'encapsulation des ressources autochtones dans les jetables que l'interne de fournir leurs propres finalisation (avec un certain nombre d'autres avantages, comme le retrait de la fenêtre au cours de P/Invoke où un natif de la poignée pourrait être perdu en raison d'un asynchrones exception).
Il suffit de définir un SafeHandle rend cette Triviale:
Permet de simplifier le contenant de type:
GC.SuppressFinalize
dans cet exemple. Dans ce contexte, SuppressFinalize ne doit être appelée que siDispose(true)
s'exécute avec succès. SiDispose(true)
échoue à un certain point, après la finalisation est supprimée, mais avant que toutes les ressources (en particulier non managés) sont nettoyés, puis vous voulez toujours la finalisation de se produire dans le but de faire autant de nettoyage possible. Mieux déplacer leGC.SuppressFinalize
appel dans leDispose()
méthode après l'appel àDispose(true)
. Voir Cadre des lignes Directrices de Conception et ce post.Je ne le pense pas. Vous avez plus de contrôle lors de l'Éliminer est appelée, ce qui signifie que vous pourrait, en théorie, écrire disposition du code qui fait des hypothèses sur (par exemple) l'existence d'autres objets. Vous n'avez aucun contrôle sur le moment où le finaliseur est appelé, de sorte qu'il serait terrible d'avoir le finaliseur appeler automatiquement Disposer sur votre compte.
EDIT: je suis allé loin et testé, juste pour s'assurer que:
Pas dans le cas que vous décrivez,
Mais le GC va appeler le Finaliseur pour vous, si vous en avez un.
CEPENDANT. La prochaine collecte de déchets ,au lieu d'être recueillies, l'objet va aller dans la finalisation québec, tout est connu, c'finaliseur de l'appelé. La prochaine collection après qu'il sera libéré.
En fonction de la pression sur la mémoire de votre application, vous ne pouvez pas avoir un gc pour que l'objet de la génération pour un certain temps. Ainsi, dans le cas de le dire, un flux de fichier ou d'une base, vous pourriez avoir à attendre un certain temps pour que la ressource non managée pour être libéré dans le finaliseur appel pour un tandis que, à l'origine de certains problèmes.
Non, il n'est pas appelé.
Mais cela le rend facile pour n'oubliez pas de jeter vos objets. Utilisez simplement le
using
mot-clé.J'ai fait le test suivant pour cela:
using
mot-clé...Le GC pas appel d'aliéner. Il peut appelez votre outil de finalisation, mais même cela n'est pas garanti dans toutes les circonstances.
Voir ce l'article pour une discussion de la meilleure façon de gérer cela.
La documentation sur IDisposable donne une assez clair et détaillé explication du comportement, ainsi que l'exemple de code. Le GC ne vais PAS appeler la
Dispose()
méthode sur l'interface, mais il va appeler le finaliseur pour votre objet.La IDisposable modèle a été créé principalement pour être appelé par le développeur, si vous avez un objet qui implémente IDispose le développeur doit soit mettre en œuvre la
using
mot-clé le contexte de l'objet ou de l'appel de la méthode dispose directement.Le fail safe pour le motif est de mettre en œuvre l'outil de finalisation de l'appel de la méthode dispose (). Si vous ne le faites pas, vous risquez de créer quelques fuites de mémoire c'est à dire: Si vous créez des COM wrapper et de ne jamais appeler le Système.Moment de l'exécution.Interop.Marshall.ReleaseComObject(comObject) (ce qui serait placé dans la méthode dispose).
Il n'y a pas de magie dans le clr pour appeler des méthodes dispose automatiquement d'autres que le suivi des objets qui contiennent des finaliseurs et de les stocker dans le Finaliseur table par le GC et de les appeler lors de la partie de nettoyage heuristique coup de pied dans le GC.