2017-10-11 4 views
1

Microsoft design guidelines mention modèle Dispose et scénarios comment l'utiliser:Ai-je vraiment besoin d'un modèle de base pour le référencement d'autres objets IDisposables?

Ænglisc le modèle Dispose de base sur les types contenant des instances de types à usage unique. Voir la section Modèle d'élimination de base pour les détails sur le motif de base.

Plus tard, ils montrent le modèle Dispose de base comme suit:

public class DisposableResourceHolder : IDisposable { 

    private SafeHandle resource; // handle to a resource 

    public DisposableResourceHolder(){ 
     this.resource = ... // allocates the resource 
    } 

    public void Dispose(){ 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing){ 
     if (disposing){ 
      if (resource!= null) resource.Dispose(); 
     } 
    } 
} 

Mes des questions sont:

  1. Pourquoi avons-nous besoin de mettre en œuvre Dispose (bool) si elle a juste un seul appel avec le paramètre vrai? Il pourrait être facilement simplifié à Dispose() {resource?.Dispose();} sans paramètre. Notez que nous n'avons pas besoin de finaliseur ici car les objets que nous référençons sont gérés et ont leurs propres finaliseurs, donc ils ne seront pas divulgués.
  2. Pourquoi recommandent-ils d'appeler le GC.SuppressFinalize(this) sans avoir de finaliseur? De toute façon, le GC n'appellerait pas le finaliseur parce qu'il n'existe pas!
  3. Le seul cas où je vois le besoin de Dispose (bool) est quand nous avons vraiment des références non gérées, qui n'implémente pas IDisposable ni finalizer (comme montré dans this article). Mais alors la signification de bool disposing serait bool includingManagedResources. Alors, pourquoi cela est-il si trompeur de «disposer» de ce qu'il devrait faire en fait?
+1

Ce n'est pas le cas. Microsoft s'inquiète de ces choses parce qu'ils ont écrit des classes qui ont des finaliseurs. N'écrivez jamais votre propre finaliseur. Il a juste fallu du temps à Microsoft pour le découvrir, puis ils ont créé les classes SafeHandle. –

+1

Le motif derrière ce modèle est celui qui peut hériter de votre classe et cette classe héritée peut avoir le finaliseur. Et non - vous n'avez pas besoin de faire ça. – Evk

+0

@Evk qui a vraiment du sens ... Merci! –

Répondre

1
  1. D'autres classes peuvent hériter de votre classe. Considérant que la classe dérivante contient également des ressources non managées (recommandées ou non), cette classe doit alors ajouter le finaliseur appelant Dispose(false). Si votre classe était scellée, je serais d'accord avec vous. Parce que la méthode void Dispose() ne devrait pas être virtual suivant les directives de Microsoft et donc dériver des classes n'auraient alors aucune chance de supprimer la finalisation après la mise au rebut. Votre implémentation n'a peut-être pas besoin d'un finaliseur, mais probablement de classes dérivées.

  2. Il est appelé disposing sans raison particulière à mon avis. Personnellement, je le renommerais aussi.

Quoi qu'il en soit, de mon point de vue, ce n'est pas une bonne approche de combiner des ressources gérées et non gérées. Comme déjà mentionné dans le commentaire, même Microsoft recommande d'encapsuler les ressources non gérées dans les ressources gérées, donc les cas où vous avez besoin d'implémenter des finaliseurs sont probablement rares. Je ne me souviens pas quand je l'ai fait moi-même la dernière fois.

Je ne tiens pas non plus à la mise en œuvre des directives pour des raisons multiples, comme une dénomination trompeuse ou parce que c'est difficile à comprendre. Une approche alternative serait this answer.

+0

Point 2 besoin [la citation requise]. La seule chose que je peux trouver qu'il ne devrait pas être virtuel seulement si la classe implémente le modèle jetable. –

+0

@HansPassant Le document lié à l'origine indique déjà "NE PAS rendre la méthode Dispose sans paramètre virtuelle.". Edit: Je pense que je comprends maintenant votre commentaire. Il n'est bien sûr pas interdit d'écrire une méthode de disposition virtuelle. Ce n'est pas la façon recommandée en ce qui concerne le document référencé. L'approche alternative que j'ai ajoutée, qui ne colle pas à ces lignes directrices, le fait différemment. – Peit

+0

A droite, ce n'est qu'un conseil judicieux pour le modèle jetable, Dispose (bool) est déjà virtuel. C'est très bien quand vous n'utilisez pas le motif. Et recommandé sauf si vous déclarez la classe scellée. –