On me demande d’implémenter IDisposable sur des objets qui sont des ressources gérées à 100%, qui ne contiennent aucun flux et aucune ressource volumineuse.

Je comprends limportance de disposer correctement des ressources volumineuses et non gérées, mais quen est-il de lautre côté de léquation?

Pour un objet qui ne bénéficie pas de limplémentation dIDisposable (petits objets entièrement gérés) , quel impact négatif peut avoir GC.SuppressFinalize, le cas échéant?

Commentaires

  • On dirait une optimisation prématurée. Êtes-vous en mesure de demander à la personne qui vous a demandé de faire cela les résultats obtenus grâce au profilage et à lanalyse comparative qui montrent que lajout de IDisposable dans ce cas améliore lempreinte mémoire?
  • @MainMa Non, mais cela ne ma ' pas mempêcher de demander de toute façon. Le résultat a été une réponse de 5 minutes de " cest juste la façon dont nous ' lavons toujours fait, vous le faites aussi ".
  • Eh bien, il est possible dimplémenter IDisposable sans écrire de destructeur / finaliseur. Je ne ' ne sais pas si la personne qui vous a demandé dimplémenter IDisposable voulait dire que vous deviez également créer un destructeur. Bien sûr, si la classe na pas de destructeur, il ny a aucun point dans GC.SuppressFinalize. Si la classe a un destructeur, assurez-vous de dire GC.SuppressFinalize(this) lorsque votre méthode Dispose est exécutée. Sinon, linstance ne sera pas récupérée facilement, elle sera mise en file dattente sur une file dattente de finaliseur et ne sera collectée que dans une collecte de génération 2.
  • @JeppeStigNielsen La question indique que les objets sont entièrement gérés ressources, donc il ny a ' pas besoin davoir un finaliseur. Sil y en a un, nous savons que ' est faux.

Réponse

Le seul objectif de GC.SuppressFinalize est:

dempêcher le finaliseur de libérer des ressources non gérées qui ont déjà été libérées par limplémentation IDisposable.Dispose.

Source: MSDN

Une fois que vous avez supprimé lobjet, vous devriez en effet appeler GC.SuppressFinalize(this);, comme indiqué dans une réponse à la question  » Quand dois-je utiliser GC.SuppressFinalize ()? « . La règle danalyse de code «  CA1816 est également utile.

Maintenant, implémentation de IDisposable sur les objets qui nont pas de ressources non gérées semblent assez étranges et discutables. Puisque la seule raison que la personne vous a donnée était: « cest juste la façon dont nous » lavons toujours fait, vous le faites aussi « , au lieu de fournir des données de profilage / benchmarking qui montrent que lajout de IDisposable améliorera quelque chose dans un cas spécifique, il ny a aucune raison réelle de le faire.

Cela poserait-il des problèmes de performances? Difficile à dire: cela dépendrait dun cas particulier.

cela pose dautres problèmes? Bien sûr. Sans compter le fait que IDisposable est pénible à implémenter, si cette pratique est trop utilisée, le code devient illisible et impossible à maintenir:

public int ComputePrice(Rebate rebate) { using (var currentCurrency = this.User.FindCurrency()) { using (var priceWithoutRebate = this.GetPurePrice()) { using (var canApplyRebate = rebate.CanApplyTo(this)) { if (!canApplyRebate) { return priceWithoutRebate; } using (var priceWithRebate = priceWithoutRebate.Apply(rebate)) { return priceWithRebate; } } } } } 

Commentaires

  • Eh bien, je crois que lhistoire est quil y a longtemps, ils avaient un lien / des problèmes de fuite de flux, probablement dus à une connexion / commande de code ADO.NET qui fuyait, et cela a provoqué des fuites massives de ressources. Ils savaient que limplémentation dIDisposable sur tout résoudrait le problème, cest ce quils ont fait, et cela a fonctionné. implémentez-le sur la plupart des objets.
  • @AndrewHoffman: cela semble être une explication plausible. Mais cela ne justifie toujours pas ' la pratique actuelle.

Réponse

Vous nêtes pas obligé dutiliser le modèle Dispose + Finalizer lourd (« douloureux ») sur une classe IDisposable, if la classe est scellée et la classe na pas de ressources non gérées.

Dans cette situation, vous pouvez utiliser un sous-ensemble du modèle Dispose + Finalizer, qui na que public Dispose(), na pas de finaliseur et la classe est scellée.

La raison du scellement de la classe est déviter les problèmes de « Et si une classe enfant a des ressources non gérées? » et « Et si une classe enfant à lavenir avait des ressources non gérées? »

Joe Duffy, anciennement de Microsoft, a un long article (plus de 30 pages) qui explique comment implémenter correctement IDisposable, et toutes les implémentations du sous-ensemble de permutation.

Les contributeurs à larticle incluent Herb Sutter, Brian Grunkemeyer, Jeff Richter et dautres personnalités du C #. Larticle est beaucoup plus détaillé que ce qui est présenté sur MSDN.

Hélas, le nouveau moteur de blog de Joe Duffy n’a pas réussi à conserver l’article original de 2005, il semble donc quelque peu bouché. Voici le lien: http://joeduffyblog.com/2005/04/08/dg-update-dispose-finalization-and-resource-management/

Jaimerais pouvoir joindre mon document MS-Word qui contient lintégralité de larticle de Joe Duffy dans un bien meilleur format. 🙁

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *