Question

Quand devrais-je implémenter IDispose sur une classe plutôt que sur un destructeur? Je lis 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", par opposition à l'attente du garbage collector. Est-ce correct?

Est-ce que cela signifie que je devrais toujours appeler explicitement Dispose sur un objet? Quels sont quelques exemples courants de cela?

Était-ce utile?

La solution

Un finaliseur (ou destructeur) fait partie de la récupération de place (GC). Il est indéterminé quand (ou même si) cela se produit, car la GC se produit principalement à la suite d’une pression de la mémoire (c’est-à-dire qu’elle nécessite 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, IDisposable est utilisé pour nettoyer de manière déterministe , c’est-à-dire maintenant. Il ne collecte pas la mémoire de l'objet (qui appartient toujours à GC) - mais sert par exemple à fermer des fichiers, des connexions à une base de données, etc.

Il existe de nombreux sujets précédents sur ce sujet:

Enfin, notez qu'il n'est pas rare qu'un objet IDisposable ait également un finaliseur; Dans ce cas, Dispose () appelle généralement GC.SuppressFinalize (this) , ce qui signifie que GC n'exécute pas le finaliseur. Il jette simplement la mémoire (beaucoup moins chère). . Le finaliseur continue de fonctionner si vous oubliez Dispose () de l'objet.

Autres conseils

Le rôle de la méthode Finalize () est de garantir qu'un objet .NET peut nettoyer les ressources non gérées lors de la récupération des ordures . Toutefois, 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 compter sur le garbage collection. Pour cela, vous devez implémenter l'interface IDisposable et libérer vos ressources dans la méthode Dispose () .

Il existe une très bonne description sur MSDN :

  

L’utilisation principale de cette interface est    libérer les ressources non gérées .   Le ramasse-miettes automatiquement   libère la mémoire allouée à un   objet géré lorsque cet objet est non   plus utilisé. Cependant, ce n'est pas   possible de prédire quand les ordures   la collecte aura lieu . En outre,   le ramasse-miettes n'a pas   connaissance des ressources non gérées   comme les poignées de fenêtre ou ouvert   fichiers et les flux.

     

Utilisez la méthode Dispose de cette   interface pour publier explicitement   ressources non gérées conjointement   avec le ramasse-miettes. le    consommateur d'un objet peut appeler cette méthode lorsque l'objet n'est pas   besoin plus longtemps.

La seule chose qui devrait figurer dans un destructeur C # est cette ligne:

Dispose(False);

C'est ça. Rien d’autre ne devrait être dans cette méthode.

Votre question concernant le fait de toujours appeler Éliminer est généralement un débat houleux. Voir ce blog pour une perspective intéressante émanant de personnes respectées de la communauté .NET.

Personnellement, je pense que la position de Jeffrey Richter selon laquelle appeler Dispose n'est pas obligatoire est incroyablement faible. Il donne deux exemples pour justifier son opinion.

Dans le premier exemple, il déclare qu'appeler Dispose sur les contrôles Windows Forms est fastidieux et inutile dans les scénarios classiques. Cependant, il omet de mentionner que Dispose est en fait appelé automatiquement par les conteneurs de contrôle dans ces scénarios classiques.

Dans le deuxième exemple, il indique qu'un développeur peut supposer à tort que l'instance de IAsyncResult.WaitHandle doit être supprimée de manière agressive sans que la propriété initialise paresseusement le descripteur d'attente, ce qui entraîne une pénalité de performance inutile. Cependant, le problème de cet exemple est que le IAsyncResult n’adhère pas aux directives publiées par Microsoft concernant le traitement des objets IDisposable . C'est-à-dire que si une classe contient une référence à un type IDisposable , la classe elle-même devrait implémenter IDisposable . Si IAsyncResult a suivi cette règle, sa propre méthode Dispose peut prendre la décision concernant les membres qui doivent être éliminés.

Donc, à moins que quelqu'un ait un argument plus convaincant, je vais rester dans le "toujours appeler Dispose". camp avec la compréhension qu'il va y avoir quelques cas marginaux qui découlent principalement de mauvais choix de conception.

C'est très simple, vraiment. Je sais que la réponse a été donnée, mais je vais réessayer, mais je vais essayer de garder les choses aussi simples que possible.

Un destructeur ne devrait généralement jamais être utilisé. Il est seulement exécuté. Net veut le faire fonctionner. Il ne fonctionnera qu'après un cycle de collecte de déchets. Il se peut qu’il ne soit jamais exécuté pendant le cycle de vie de votre application. Pour cette raison, vous ne devriez jamais mettre de code dans un destructeur qui doit être exécuté. Vous ne pouvez pas non plus vous fier à l'existence d'objets existant dans la classe lors de son exécution (ils ont peut-être déjà été nettoyés, l'ordre dans lequel les destructeurs étant exécutés n'étant pas garanti).

IDisposible doit être utilisé chaque fois que vous avez un objet qui crée des ressources qui nécessitent un nettoyage (par exemple, des descripteurs de fichiers et graphiques). En fait, nombreux sont ceux qui soutiennent que tout ce que vous mettez dans un destructeur doit être inséré de manière indissociable pour les raisons susmentionnées.

La plupart des classes appelleront disposer lorsque le finaliseur sera exécuté, mais il s’agit simplement d’une sécurité et ne doit jamais être invoqué. Vous devez explicitement jeter tout ce qui implémente IDisposable lorsque vous 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.

Voici un autre excellent article qui élimine une partie de la brume entourant IDisposable, le GC et l’élimination.

WebLog WebLog de Chris Lyons: démystifier le retrait

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top