64 votes

Destructor vs IDisposable?

J'ai lu à propos de l'élimination des objets/interface IDisposable et destructeurs en C#, mais pour moi, ils semblent faire la même chose?

Quelle est la différence entre les deux? Pourquoi voudrais-je utiliser l'un plutôt que l'autre? En fait, dans cet exemple (lien ci-dessous) ce code utilise à la fois l'interface IDisposable et un destructeur:

http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

Le commentaire dit que le destructeur est si la finalisation du code n'est pas utilisé, mais comment puis-je décider quand utiliser l'un plutôt que l'autre?

82voto

Greg Beech Points 55270

J'ai écrit un assez approfondie post qui devrait aider à expliquer les finaliseurs, IDisposable, et lorsque vous devez utiliser l'un ou l'autre: http://gregbee.ch/blog/implementing-and-using-the-idisposable-interface

Probablement la partie la plus pertinente est cité ci-dessous:

Lorsque vous utilisez les ressources non managées tels que les poignées et base de données connexions, vous devez vous assurer que ils sont détenus pour le montant minimum de temps, en utilisant le principe de l' acquérir la fin et la libération anticipée. En C++ relâcher les ressources est généralement fait dans le destructeur, qui est de façon déterministe exécuter au point où l'objet est supprimé. L' .NET de l'exécution, cependant, utilise une poubelle collector (GC) pour nettoyer et récupérer la mémoire utilisée par des objets qui ne sont plus accessible; que cela fonctionne sur un périodiquement, cela signifie que le point de votre objet est nettoyée est non déterministe. La conséquence de c'est que les destructeurs n'existent pas pour les objets gérés comme il n'y a pas de déterministe de place pour courir.

Au lieu de destructeurs, C# a les finaliseurs qui sont mis en œuvre par substitution de la méthode Finalize défini sur la base de la classe d'Objet (si C# un peu de prêter à confusion, utilise le C++ destructeur de syntaxe ~de l'Objet). Si un objet remplace le Finaliser méthode alors plutôt que d'être recueillies par le GC, il est hors de la portée, la GC place sur un finaliseur la file d'attente. Dans le prochain cycle de GC tous finaliseurs dans la file d'attente (sur un seul thread dans le courant la mise en œuvre) et la mémoire à partir de la finalisation des objets récupérés. C'est assez évident, d'après cela pourquoi ne pas vous voulez faire nettoyer dans un finaliseur: il prend deux GC cycles de recueillir les de l'objet au lieu d'un et il est un seul thread où tous les finaliseurs sont exécutez alors que tous les autres thread suspendu, il va faire mal les performances.

Donc, si vous n'avez pas destructeurs, et vous ne voulez pas quitter le nettoyage le finaliseur, la seule option est manuellement, de façon déterministe, propre l'objet. Entrez le IDisposable interface qui fournit une norme pour soutenir cette fonctionnalité et définit une seule méthode, d'en Disposer, où vous avez mis dans la logique de nettoyage pour l'objet. Lorsqu'il est utilisé dans une enfin bloc, cette interface permet à l' des fonctionnalités équivalentes à les destructeurs. La raison pour enfin les blocs de code est principalement pour le support l'interface IDisposable; c'est pourquoi C++ utilise tout simplement essayer de/sauf comme il est pas besoin d'un bloc finally avec les destructeurs.

23voto

Ian Boyd Points 50743

Version courte

Un finaliseur vous donne la possibilité de disposer de ressources non managées dans le cas où l'utilisateur de votre objet oublié d'appeler IDisposable.Dispose.

Si votre objet implémente IDisposable, l'utilisateur de votre objet doit appeler .Dispose. Vous n'avez pas avoir à nettoyer l'utilisateur du désordre; mais c'est une belle chose à faire.


Mon plus populaires de réponse sur Stackoverflow vous guide depuis le début, pourquoi vous avez IDisposable, ce qu'il doit faire, ce que votre finaliseur peut faire, ce qu'il ne devrait pas le faire.

Cette réponse fond visages

a été utilisé pour décrire ça :P

5voto

David Lee Points 121

Avoir de destructeur (~Object()) dans la gestion de langage de programmation est le plus dummest idée. C'est parfaitement logique pour non géré langages comme C,C++ pour avoir des destructeurs, car ils utilisent de l'idiome RAII mais pour géré comme Java,C#, tellement absurde.

Il a été souligné par Joshua Bloch, ancien chef de projet en Java Cadre de Collecte, que l'idée de la méthode finalize () (ce qui est équivalent à C#, C++ comme destructeur) en Java a été la plus grande erreur jamais fait. Même que C#, finallize() en Java, donne de frais généraux pour les "nouveaux" comme il doit être ajouté à la finallizer file d'attente lors de l'allocation. De plus, le Collecteur d'Ordures doivent pop et exécuter finallize() dans la file d'attente, donc deux fois les frais généraux au cours de gc.

C# a beaucoup de fonctionnalités améliorées comme "à l'aide de(IDisposable) {}", qui permettent non seulement la IDisposable variable à être confiné à la portée de "l'aide", mais aussi de garantir que c'est le nettoyage. Ma question est, pourquoi C# suivre le même sentier de Java, qui conduisent à une grande erreur. Peut-être si le développement de dotnet commencé après 2003 ~ 2005, lorsque de nombreux architectes Java trouvé l'erreur de finallize(), alors l'erreur aurait été empêché.

Beaucoup de bonnes idée d'une langue est souvent transférés à d'autres langues comme le "IDisposable/à l'aide de combo" en C# qui a été transférée à Java 1.7, dans son "essai(objet-à-jeter) {}". Mais ses dommage que la langue architectes manquera pas de découvrir la mauvaise idée déguisée comme une bonne idée au cours de son transfert de l'un à l'autre.

Mon conseil est de ne jamais utiliser d' ~Destructeur() et le bâton avec IDisposable/à l'aide de combo si vous devez manuellement le nettoyage de la ressource non managée comme des connexions de base de données.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X