2010-11-03 27 views
8

Lorsque j'ai lu quelques articles sur la gestion de la mémoire en C#, j'ai été perturbé par les méthodes Finalizer.Bons exemples d'utilisation de Finalizers en C#

Il y a tellement de règles compliquées qui les concernent. Par exemple, personne ne sait quand les finaliseurs seront appelés, ils appellent même si le code dans ctor lance, CLR ne garantit pas que tous les finaliseurs seront appelés lorsque les programmes shutdowt, etc

Pour ce que les finaliseurs peuvent être utilisés en réel la vie?

Le seul exemple que j'ai trouvé était un programme qui bipe lorsque GC démarre.

Utilisez-vous des finaliseurs dans votre code et pouvez-vous avoir de bons échantillons?

UPD:

Finaliseurs peut être utilisé lorsque developpeurs veulent faire en sorte que une classe toujours correctement par IDisposable disposés. (link, Merci Steve Townsend)

+4

J'ai seulement écrit une poignée de finaliseurs dans les 5 dernières années de projets sur lesquels j'ai travaillé et ils étaient tous pour des classes qui fonctionnaient avec une API non gérée héritée. En fonctionnement normal, les finaliseurs n'ont jamais été appelés, car les objets ont été éliminés avant d'être éligibles à la récupération de place, et la finalisation a été explicitement supprimée. –

+0

@Dan Bryant - oui - n'a pas vu cela avant de faire ce point ma réponse ... –

+1

J'ai toujours pensé que les finaliseurs étaient là pour disposer des ressources non managées comme un fail safe dans le cas où l'IDisposable.Dispose() ne s'appelle pas (SuppressFinalize –

Répondre

4

Il y a une discussion exhaustive de l'utilisation Finalizer, avec des exemples, here. Lien courtoisie de @SLaks au a related answer.

Voir aussi here pour un résumé plus concis de quand vous en avez besoin (ce qui est «pas très souvent»).

Il existe une bonne réponse précédente here avec un autre bon exemple concret.

Pour résumer avec un extrait pertinent:

Finaliseurs sont nécessaires pour garantir la libération des ressources rares de nouveau dans le système d'exploitation comme les poignées de fichiers, prises, objets du noyau, etc.

Pour plus corriger exemples réels, parcourir les classes affectées dans le .Net Framework cette recherche MSDN:

http://social.msdn.microsoft.com/Search/en-US?query=%22.Finalize%22&ac=8

Une raison valable, je peux penser quand vous pourriez avoir besoin d'utiliser un finaliseur est si vous enveloppez un code natif tiers API dans un emballage géré, et la bibliothèque API de code natif sous-jacent exige la libération rapide de utilisé les ressources du système d'exploitation.

3

La meilleure pratique que je connais est simple, ne les utilisez pas. Il peut cependant y avoir quelques cas où vous voulez utiliser un finaliseur, en particulier lorsque vous manipulez des objets non gérés et que vous ne pouvez pas implémenter le pattern Dispose (je ne connais pas les problèmes hérités) alors vous pouvez implémenter la méthode Finalize avec précaution. la performance de votre système, rendre vos objets morts-vivants et d'autres scénarios possiblement étranges, en tenant compte des exceptions car ils sont inaccessibles :)).

Dans 99% des cas, il suffit d'écrire le motif d'élimination et d'utiliser cette méthode pour nettoyer après vous-même et tout ira bien.

+0

Je ne peux pas comprendre ce que vous dites ici (vous pourriez vouloir formaliser cela un peu) mais je suis sûr à 100% que dans 99% des cas vous ne voulez pas aller près des finalisers. – annakata

+0

C'est exactement ce que je dis. Je pourrais éditer la réponse si elle n'est pas claire. Les finaliseurs sont dangereux et nécessitent beaucoup de prudence lors de leur mise en œuvre. Et comme les gars l'ont dit avant moi, ils ne sont nécessaires que lorsqu'il s'agit de ressources non gérées. Mais l'interfaçage avec la technologie héritée ou l'utilisation de certaines bibliothèques c/c + + peut être un moyen de l'utiliser. – luckyluke

+0

Une classe ne devrait presque jamais avoir de finaliseur à moins que l'objectif de la classe ne tourne autour de lui (comme c'est le cas avec SafeHandle, par exemple). Si un objet compliqué demande l'usage exclusif de quelque chose qui lui survivra, il devrait créer un autre objet dont le seul but est de gérer cette chose. De nombreuses complications surviennent si un objet avec un finaliseur contient des références à d'autres objets, qui peuvent à leur tour contenir des références à d'autres objets, etc. Il est ironique que le pattern Dispose fournisse un support explicite pour qu'une classe dérivée ajoute un finalizer. une bonne idée. – supercat