Duplication possible:
Le Garbage Collector va-t-il appeler IDisposable.Dispose pour moi?
J’ai une classe qui a des ressources non gérées. Ma classe implémente l’interface IDisposable
et libère les ressources non managées dans la méthode Dispose()
. Dois-je appeler la méthode Dispose()
ou sera-t-elle appelée automatiquement d’une manière ou d’une autre? Est-ce que le garbage collector l’appellera?
Dispose()
ne sera pas appelée automatiquement. S’il y a un finaliseur, il sera appelé automatiquement. L’implémentation d’ IDisposable
permet aux utilisateurs de votre classe de libérer des ressources au début, au lieu d’attendre le ramasse-miettes.
La méthode préférable pour un client consiste à utiliser l’instruction using
qui gère l’appel automatique de Dispose()
même s’il existe des exceptions.
Une implémentation correcte de IDisposable
est:
class MyClass : IDisposable { private bool disposed = false; void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if(!disposed) { if(disposing) { // Manual release of managed resources. } // Release unmanaged resources. disposed = true; } } ~MyClass() { Dispose(false); } }
Si l’utilisateur de la classe appelle Dispose()
le nettoyage est effectué directement. Si l’object est capturé par le ramasse-miettes, il appelle Dispose(false)
pour effectuer le nettoyage. Veuillez noter que lorsque vous ~MyClass
appelé depuis le finaliseur (la méthode ~MyClass
), les références gérées peuvent ne pas être valides. Par conséquent, seules les ressources non managées peuvent être libérées.
Pour vous assurer que les ressources sont correctement éliminées, vous devez implémenter IDisposable
et appeler Dispose
dans le destructeur (finalizer).
class Foo : IDisposable { private bool m_disposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ~Foo() { Dispose(false); } protected void Dispose(bool disposing) { if (!m_disposed) { if (disposing) { //release managed resources } //release unmanaged resources m_disposed = true; } } }
Si vous instanciez votre object dans une instruction using
, Dispose () est appelé pour vous lorsque le code quitte le bloc using
using(var myObject = new MyDisposableObject()) { blah(); } // Dispose() is called here (or whenever the code exits the block)
Si vous n’utilisez pas using
, alors c’est à vous (le code d’appel) de disposer de votre object en appelant explicitement Dispose ().
En outre, vous (l’implémenteur de MyObject) pouvez append un support pour un finaliseur au cas où votre appelant n’appelle pas Dispose (). Plus d’infos ici .
Vous devrez appeler cette méthode manuellement, peut-être dans une construction comme
using(var myclass = new MyClass()) { // do something with myclass } // now 'myclass'is Disposed