web-dev-qa-db-fra.com

Dispose vs Dispose (bool)

Je suis confus à propos de disposer. J'essaie d'obtenir que mon code dispose des ressources correctement. J'ai donc configuré mes classes en tant que IDisposable (avec une méthode Dispose), en veillant à ce que la méthode Dispose soit appelée.

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

Je ne vois pas de méthode Dispose qui prend un bool. Dois-je en faire un? Si oui, pourquoi? Pourquoi ne pas simplement avoir une méthode qui s'appelle quand il se débarrasse? 

J'ai vu du code ici: http://msdn.Microsoft.com/en-us/library/ms244737.aspx qui montre comment créer une méthode de mise au rebut qui prend une valeur booléenne. Il dit que c'est pour les ressources natives par rapport aux ressources gérées. Mais je pensais que le but de disposer était destiné uniquement aux ressources non gérées.

En outre, la ligne à propos de laquelle FXCop se plaint est la suivante:

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

Ça dit: 

CA1063: Microsoft.Design: Modifiez 'OwnerDrawnPanel. ~ OwnerDrawnPanel ()' afin qu'il appelle Dispose (false) puis retourne.

Mais Font n'a pas de Disole (que je peux trouver).

Résumer:

Pourquoi ai-je besoin d'un Dispose (boolé)? et si je le fais, pourquoi Font n'en a-t-il pas? et comme il ne l’a pas, pourquoi FXCop me demande de l’utiliser?


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

La réponse telle que je la vois:

La disposition des ressources "non gérées" se divise en deux catégories:

  1. Les ressources sont encapsulées dans une classe gérée (par exemple, Bitmap, Police de caractères, etc.), mais doivent toujours être appelées Dispose pour être nettoyées correctement.
  2. Les ressources que vous avez allouées, qui sont des représentations de ressources natives (c'est-à-dire les contextes de périphérique qui doivent être libérés)

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

  1. Lorsque Dispose est directement appelé sur votre objet, vous souhaitez libérer les deux types de ressources "non gérées". 
  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 ramasse-miettes en prendra soin quand il les nettoiera. Vous devez uniquement vous soucier des vraies ressources natives que vous avez allouées (le cas échéant).
33
Vaccano

IDisposable fournit une méthode avec la signature 

public void Dispose()

Les meilleures pratiques de Microsoft ( http://msdn.Microsoft.com/en-us/library/fs2xkftw.aspx ) recommandent de créer une deuxième méthode privée avec la signature

private void Dispose(bool)

Votre méthode Dispose publique et Finalizer doivent appeler cette méthode privée Dispose pour éviter de supprimer plusieurs fois les ressources gérées.

Vous pouvez corriger l'avertissement que vous obtenez en implémentant IDisposable et en supprimant votre objet de police dans la méthode dispose ou en créant une méthode Dispose(bool) dans votre classe et en demandant au finaliste d'appeler cette méthode.

7
Kyle Trauberman

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

8
Kumar

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

Si un utilisateur de votre classe oublie d'appeler Dispose sur votre méthode, vous libérerez les ressources non gérées uniquement en appelant Dispose(false) dans la Finalizer.

Dans le cas où IDispose est appelé correctement, vous appelez la disposition sur les ressources gérées et aussi / vous occupez des personnes non gérées.

Le drapeau est de distinguer les deux cas. 

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

7
Aryabhatta

FxCop indique que vous devez implémenter le motif Jetable comme décrit ici . Notez que vous devez pas utiliser les finaliseurs pour supprimer les ressources gérées telles que _font est. Les finaliseurs sont utilisés pour nettoyer unmanaged resources. Si vous n'exécutez pas la logique de nettoyage dans la méthode Dispose de votre (sous) classe, elles sont exécutées de manière non déterministe par le garbage collector.

3
m0sa

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 ramasse-miettes. Par exemple, dans votre code, vous n'avez pas besoin de disposer de l'objet _font dans le destructeur de la OwnerDrawnPanel. Puisque le panneau est en train d'être nettoyé par le GC, il en sera de même pour _font, car le panneau était le seul à l'avoir référencé, n'est-ce pas?

En règle générale, si vous possédez des objets jetables, il vous suffit de les disposer lorsque votre propre méthode Dispose a été appelée. MaisPASdans 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
Fyodor Soikin

Vous ne devriez presque jamais avoir besoin d'utiliser des finaliseurs. Ils ne concernent que les classes contenant directement des ressources / non gérées. Dans .NET 2.0+, elles doivent être encapsulées dans SafeHandle. 

2
Mark Sowul

Je pense que Dispose(true) libérera à la fois les ressources gérées et non gérées car nous n'avons pas besoin d'appeler à nouveau la finalisation. C'est pourquoi nous écrivons GC.SupressFinalize() après Dispose(true)

Nous appelons Dispose(false) dans les destructeurs pour libérer des ressources non gérées et nous allons être appelés par Runtime et non par le code de l'utilisateur.

2
Ratnesh Sinha

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 le fait que Dispose soit appelé par votre code ou par le runtime.

1
Ben Hoffstein

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

0
OrahSoft

Le modèle d'implémentation des finaliseurs publics public void Dispose(), protected virtual void Dispose(bool) et ~ClassName() constitue une pratique recommandée recommandée par Microsoft comme moyen d'organiser avec soin votre code de nettoyage pour les ressources gérées et non gérées. 

Fondamentalement, le code qui utilise votre Disposable class devrait call Dispose(), mais si ce n'est pas le cas, le finaliseur ~ClassName() sera appelé par Garbage Collection, et en fonction de celui utilisé, vous définissez l'argument 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 recommander d’utiliser cette pratique dans votre méthode de finalisation ~ClassName().

0
Sam Skuce