64

Possible Duplicate:
Will the Garbage Collector call IDisposable.Dispose for me?

I have a Class which has some unmanaged resources. My class implements the IDisposable interface and releases the unmanaged resources in the Dispose() method. Do I have to call the Dispose() method or will it be automatically called somehow? Will the Garbage Collector call it?

Community
  • 1
  • 1
Padeep
  • 641
  • 1
  • 5
  • 3

4 Answers4

79

Dispose() will not be called automatically. If there is a finalizer it will be called automatically. Implementing IDisposable provides a way for users of your class to release resources early, instead of waiting for the garbage collector.

The preferable way for a client is to use the using statement which handles automatic calling of Dispose() even if there are exceptions.

A proper implementation of IDisposable is:

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); }
}

If the user of the class calls Dispose() the cleanup takes place directly. If the object is catched by the garbage collector, it calls Dispose(false) to do the cleanup. Please note that when called from the finalizer (the ~MyClass method) managed references may be invalid, so only unmanaged resources can be released.

Anders Abel
  • 67,989
  • 17
  • 150
  • 217
  • 1
    A late addition: that finalizer is not called immediately when the reference is out-of-scope, but "some time (possibly: much) later" when the GC comes around to it. So: *do not depend on the finalizer for cleanup* – Hans Kesting Mar 15 '18 at 12:08
  • 2
    It sounds like you're saying that Dispose is called automatically if a Finalizer exists (even if the Finalizer does not call the Dispose method). But an explicit Finalizer doesn't automatically call Dispose does it, unless you explicitly code the Finalizer to call Dispose. – Developer Webs Oct 16 '19 at 15:01
  • shouldn't "void Dispose()" be "public void Dispose()"? I am getting a compiler error if i omit the public... perhaps something has changed since 2011.. Can i edit your post and fix it? – Luca Aug 03 '23 at 09:28
11

You will have to call this method manually, maybe (assuming that "MyClass" implements "IDisposable") in a construct like

using(var myclass = new MyClass())
{
   // do something with myclass
}

// now 'myclass'is Disposed

In C# 8.0, you can write as below statement:

using var myclass=new MyClass();

and the "myclass" will be disposed automatically at the end of the scope.

The advantage of the using statement (compared to calling Dispose() explicitly) is that Dispose() is called no matter how you exit this block: by running past the end, encountering a return statement or having an exception thrown.

Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
11

If you instantiate your object in a using statement, Dispose() is called for you when code exits the using block

using(var myObject = new MyDisposableObject())
{
  blah();
} // Dispose() is called here (or whenever the code exits the block)

If you don't use using, then it's up to you (the calling code) to dispose of your object by explicitely calling Dispose().

Also, you (the implementor of MyObject) can add support for a finalizer in case your caller doesn't call Dispose(). More info here.

Serge Wautier
  • 21,494
  • 13
  • 69
  • 110
8

To make sure the resources are correctly disposed, you need to both implement IDisposable and call Dispose in the destructor(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;
        }
    }
}
Cheng Chen
  • 42,509
  • 16
  • 113
  • 174