web-dev-qa-db-fra.com

IDisposable.Dispose () est-il appelé automatiquement?

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?

53
Padeep

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.

64
Anders Abel

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 .

8
Serge Wautier

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;
        }
    }
}
7
Cheng Chen

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
4
Hans Kesting