Disposer vs disposer (bool)

Je suis confus au sujet de disposer. J'essaie d'obtenir mon code en disposant correctement les ressources. J'ai donc configuré mes classes comme IDisposable (avec une méthode Dispose) en m'assurant que la méthode Dispose est appelée.

Mais maintenant FXCop me dit beaucoup de choses sur Disposing = false et appelle Dispose (false).

Je ne vois pas une méthode Dispose qui prend un bool. Dois-je le faire? Si oui, pourquoi? Pourquoi ne pas simplement avoir une méthode qui est appelée quand elle se débarrasse?

J'ai vu du code ici: http://msdn.microsoft.com/en-us/library/ms244737.aspx {[9] } cela montre comment faire une méthode de disposition qui prend un bool. Il dit que c'est pour les ressources natives vs gérées. mais je pensais que le but de disposer était uniquement pour les ressources non gérées.

En outre, la ligne dont se plaint FXCop est la suivante:

    ~OwnerDrawnPanel()
    {
        _font.Dispose();
    }

, Il dit:

CA1063: Microsoft.Conception: Modifier ' OwnerDrawnPanel.~OwnerDrawnPanel () ' pour qu'il appelle dispose(false), puis renvoie.

Mais la police n'a pas de Dispose (bool) dessus (que je peux trouver).

Pour résumer:

Pourquoi ai-je besoin D'un disposer (bool)? et si je le fais, pourquoi la police ne l'a-t-elle pas? et comme il ne l'a pas, pourquoi FxCop me demande-t-il de l'utiliser?


Merci pour toutes les bonnes réponses. Je crois que je comprends maintenant. Voici

La réponse telle que je la vois:

L'élimination des ressources "non gérées" se divise en deux catégories:

  1. ressources qui sont encapsulées dans une classe gérée (c'est-à-dire Bitmap, police, etc.), mais qui doivent encore être appelées pour les nettoyer correctement.
  2. les ressources que vous avez allouées, qui sont des représentations de ressources natives (c'est-à-dire des contextes de périphériques qui doivent être libérés)

Dispose(bool) est utilisé pour indiquer la différence entre les deux:

  1. lorsque Dispose est directement appelé sur votre objet, vous voulez libérer les deux types de " non gérés" ressources.
  2. lorsque votre objet est prêt pour la récupération de place, vous n'avez pas à vous soucier du premier type de ressources. Le garbage collector prendra soin d'eux quand il les nettoie. Vous n'avez qu'à vous soucier des vraies ressources natives que vous avez allouées (le cas échéant).
31
demandé sur The Smallest 2011-03-07 23:58:12

10 réponses

IDisposable fournit une méthode avec la signature

public void Dispose()

Meilleures pratiques Microsoft ( http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx ) recommande de faire une deuxième méthode privée avec la signature

private void Dispose(bool)

Votre méthode de disposition publique et Finalizer doivent appeler cette méthode de disposition privée pour éviter de disposer plusieurs fois des ressources gérées.

Vous pouvez corriger l'avertissement que vous recevez en implémentant IDisposable et en éliminant votre objet font dans la méthode dispose, ou la création d'une méthode Dispose(bool) dans votre classe, et faire votre finalizer appeler cette méthode.

7
répondu Kyle Trauberman 2011-03-07 21:06:14

Dispose(bool) est un modèle à implémenter Finalize et Dispose pour nettoyer les ressources non gérées, voir ceci pour plus de détails

8
répondu Kumar 2017-05-23 11:54:07

Dispose(bool) n'est pas destiné à être public, et c'est pourquoi vous ne le voyez pas sur Font.

Dans le cas où un utilisateur de votre classe oublie d'appeler Dispose sur votre méthode, vous libérerez les ressources non gérées seulement en faisant un appel à Dispose(false) dans le Finalizer.

Dans le cas où IDispose est appelé correctement, vous appelez le Dispose sur les ressources gérées et aussi Prenez soin des ressources non gérées.

Le drapeau est de distinguer les deux cas.

C'est un modèle recommandé par MSDN.

7
répondu 2011-03-07 21:06:08

FxCop dit que vous devez implémenter le modèle jetable comme décrit ici . Notez que vous devriez Pas utiliser des finaliseurs pour disposer des ressources gérées comme _font est. Les finaliseurs sont utilisés pour nettoyer les ressources non gérées . Si vous n'exécutez pas la logique de nettoyage dans la méthode Dispose de votre (sous)classe, ils sont exécutés de manière non déterministe par le garbage collector.

3
répondu m0sa 2011-03-07 21:13:33

Notez également que c'est très rarement que vous devez faire quoi que ce soit dans le destructeur. Régulièrement, tout est pris en charge par le garbage collector. Par exemple, dans votre code, vous n'avez pas besoin de disposer de l'objet _font dans le destructeur de OwnerDrawnPanel. Puisque le panneau est nettoyé par le GC, il en sera de même pour _font, car le panneau était le seul qui l'a référencé, n'est-ce pas?

Généralement, si vous possédez des objets jetables, vous n'avez besoin de les disposer que lorsque votre Dispose la méthode a été appelée. Mais PAS dans le destructeur. Lorsque votre destructeur est en cours d'exécution, vous pouvez parier que tous vos objets agrégés sont également nettoyés.

2
répondu Fyodor Soikin 2011-03-07 21:11:06

Vous ne devriez presque jamais avoir besoin d'utiliser des finaliseurs. Ils ne sont que pour les classes qui contiennent directement des ressources non gérées, et dans. net 2.0 + celles-ci doivent être enveloppées dans SafeHandle.

2
répondu Mark Sowul 2011-03-07 21:11:39

Je pense que Dispose(true) libérera à la fois la ressource gérée et non gérée car nous ne devons plus appeler finalize c'est pourquoi nous écrivons GC.SupressFinalize() après Dispose(true).

Nous appelons Dispose(false) dans destructors pour libérer des ressources non gérées et seront appelés par Runtime et non par le code de l'utilisateur.

2
répondu Ratnesh Sinha 2011-06-26 13:45:38

En accord avec Kumar, le modèle Dispose(bool disposing) est également documenté sur MSDN . La distinction n'est pas entre les ressources gérées et non gérées, mais si Dispose est appelé par votre code ou le runtime.

1
répondu Ben Hoffstein 2011-03-07 21:06:03

J'ai trouvé un bon article sur l'implémentation correcte de L'interface IDispose: http://msdn.microsoft.com/en-us/library/ms244737 (v=vs. 80).aspx

0
répondu OrahSoft 2011-03-07 21:07:46

Le modèle de mise en œuvre d'un public public void Dispose(), protected virtual void Dispose(bool), et ~ClassName() finalizers est une bonne pratique recommandée par Microsoft comme un moyen d'organiser soigneusement votre code de nettoyage pour les ressources gérées et non gérées.

Fondamentalement, le code qui utilise votre Disposable classe devrait appeler Dispose(), mais si ce n'est pas le cas, le finaliseur {[2] } sera appelé par Garbage Collection, et en fonction de l'un de ceux-ci est utilisé, vous définissez l'argument sur Dispose(bool) comme vrai ou faux, et dans votre Dispose(bool), Vous ne nettoyez les ressources gérées que si l'argument est vrai.

L'avertissement que vous obtenez semble spécifiquement vous recommandons d'utiliser cette pratique dans votre méthode finalize ~ClassName().

0
répondu Sam Skuce 2011-03-07 21:40:08