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).
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 disposition des ressources "non gérées" se divise en deux catégories:
Dispose (bool) est utilisé pour faire la différence entre les deux:
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.
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
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.
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.
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.
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.
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.
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.
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
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()
.