Duplicata possible:
Le garbage collector appellera-t-il 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? Le garbage collector l'appellera-t-il?
Dispose()
ne sera pas appelée automatiquement. S'il y a un finalizer il sera appelé automatiquement. L'implémentation de IDisposable
permet aux utilisateurs de votre classe de libérer les ressources plus tôt, au lieu d'attendre le garbage collector.
La manière préférable pour un client est d'utiliser l'instruction using
qui gère l'appel automatique de Dispose()
même s'il y a 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 a lieu directement. Si l'objet est intercepté par le garbage collector, il appelle Dispose(false)
pour effectuer le nettoyage. Veuillez noter que lorsqu'elles sont appelées depuis le finaliseur (la méthode ~MyClass
), Les références gérées peuvent être invalides, donc seules les ressources non gérées peuvent être libérées.
Si vous instanciez votre objet dans une instruction using
, Dispose () est appelé à votre place 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
, c'est à vous (le code appelant) de disposer de votre objet en appelant explicitement Dispose ().
De plus, vous (l'implémenteur de MyObject) pouvez ajouter la prise en charge d'un finaliseur au cas où votre appelant n'appellerait pas Dispose (). Plus d'infos ici .
Pour vous assurer que les ressources sont correctement éliminées, vous devez à la fois implémenter IDisposable
et appeler Dispose
dans le destructeur (finaliseur).
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;
}
}
}
Vous devrez devez appeler cette méthode manuellement, peut-être dans une construction comme
using(var myclass = new MyClass())
{
// do something with myclass
}
// now 'myclass'is Disposed