Quand est-ce que j'implémenterai IDispose sur une classe par opposition à un destructeur? J'ai lu cet article , mais je manque toujours le point.
Mon hypothèse est que si j'implémente IDispose sur un objet, je peux explicitement le «détruire» plutôt que d'attendre que le garbage collector le fasse. Est-ce correct?
Cela signifie-t-il que je devrais toujours appeler explicitement Dispose sur un objet? Quels sont quelques exemples courants de cela?
c#
.net
dispose
destructor
Jordan Parmer
la source
la source
using
construction.Réponses:
Un finaliseur (alias destructeur) fait partie du ramasse-miettes (GC) - il est indéterminé quand (ou même si) cela se produit, car GC se produit principalement en raison de la pression de la mémoire (c'est-à-dire qu'il faut plus d'espace). Les finaliseurs ne sont généralement utilisés que pour nettoyer les ressources non gérées , car les ressources gérées auront leur propre collecte / élimination.
Par conséquent, il
IDisposable
est utilisé pour nettoyer les objets de manière déterministe , c'est-à-dire maintenant. Il ne collecte pas la mémoire de l'objet (qui appartient toujours à GC) - mais est utilisé par exemple pour fermer des fichiers, des connexions à la base de données, etc.Il y a beaucoup de sujets précédents à ce sujet:
Enfin, notez qu'il n'est pas rare qu'un
IDisposable
objet ait également un finaliseur; dans ce cas, ilDispose()
appelle généralementGC.SuppressFinalize(this)
, ce qui signifie que GC ne lance pas le finaliseur - il jette simplement la mémoire (beaucoup moins cher). Le finaliseur s'exécute toujours si vous oubliezDispose()
l'objet.la source
Le rôle de la
Finalize()
méthode est de garantir qu'un objet .NET peut nettoyer les ressources non gérées lors du nettoyage de la mémoire . Cependant, les objets tels que les connexions à la base de données ou les gestionnaires de fichiers doivent être libérés dès que possible, au lieu de s'appuyer sur le garbage collection. Pour cela, vous devez implémenter l'IDisposable
interface et libérer vos ressources dans laDispose()
méthode.la source
Il y a une très bonne description sur MSDN :
la source
La seule chose qui devrait être dans un destructeur C # est cette ligne:
C'est tout. Rien d'autre ne devrait jamais être dans cette méthode.
la source
Votre question de savoir si vous devez toujours appeler ou non
Dispose
est généralement un débat houleux. Consultez ce blog pour une perspective intéressante de personnalités respectées de la communauté .NET.Personnellement, je pense que la position de Jeffrey Richter selon laquelle l'appel
Dispose
n'est pas obligatoire est incroyablement faible. Il donne deux exemples pour justifier son opinion.Dans le premier exemple, il dit appeler
Dispose
aux contrôles Windows Forms est fastidieux et inutile dans les scénarios traditionnels. Cependant, il omet de mentionner qu'ilDispose
est appelé automatiquement par les conteneurs de contrôle dans ces scénarios traditionnels.Dans le deuxième exemple, il déclare qu'un développeur peut supposer à tort que l'instance de
IAsyncResult.WaitHandle
doit être supprimée de manière agressive sans se rendre compte que la propriété initialise paresseusement le handle d'attente, ce qui entraîne une pénalité de performances inutile. Mais, le problème avec cet exemple est que leIAsyncResult
lui-même n'adhère pas aux propres directives publiées par Microsoft pour traiter lesIDisposable
objets. Autrement dit, si une classe contient une référence à unIDisposable
type, la classe elle-même devrait l'implémenterIDisposable
. SiIAsyncResult
cette règle était suivie, sa propreDispose
méthode pourrait prendre la décision concernant lequel de ses membres constituants doit être éliminé.Donc, à moins que quelqu'un n'ait un argument plus convaincant, je vais rester dans le camp "toujours appeler Dispose" avec la compréhension qu'il va y avoir des cas marginaux qui découlent principalement de mauvais choix de conception.
la source
C'est vraiment assez simple. Je sais que cela a été répondu, mais je vais essayer à nouveau, mais je vais essayer de rester aussi simple que possible.
Un destructeur ne doit généralement jamais être utilisé. Il est uniquement exécuté .net veut qu'il fonctionne. Il ne fonctionnera qu'après un cycle de collecte des ordures. Il se peut qu'il ne soit jamais exécuté pendant le cycle de vie de votre application. Pour cette raison, vous ne devez jamais mettre de code dans un destructeur qui «doit» être exécuté. Vous ne pouvez pas non plus compter sur l'existence d'objets existants dans la classe lors de son exécution (ils ont peut-être déjà été nettoyés car l'ordre dans lequel les destructeurs s'exécutent n'est pas garanti).
IDisposible doit être utilisé chaque fois que vous avez un objet qui crée des ressources à nettoyer (c'est-à-dire des descripteurs de fichiers et graphiques). En fait, beaucoup soutiennent que tout ce que vous mettez dans un destructeur devrait être putin IDisposable pour les raisons énumérées ci-dessus.
La plupart des classes appelleront disposer lorsque le finaliseur est exécuté, mais c'est simplement là comme une sécurité et ne doit jamais être invoqué. Vous devez explicitement supprimer tout ce qui implémente IDisposable lorsque vous en avez terminé. Si vous implémentez IDisposable, vous devez appeler dispose dans le finaliseur. Voir http://msdn.microsoft.com/en-us/library/system.idisposable.aspx pour un exemple.
la source
Voici un autre bel article qui élimine une partie de la brume entourant IDisposable, le GC et l'élimination.
Chris Lyons WebLog démystifiant Dispose
la source