1

Possible Duplicate:
Proper use of the IDisposable interface

I tried to find an actual answer to my question from books, internet and on stackoverflow, but nothing has helped me so far, so hopefully I can word my issue exact enough to make sense.

In general I always found the same basic usage of how to free memory, which is approx. as follows and I do understand the code itself:

public class MyClass : IDisposable
{
    bool disposed = false;
    public void Dispose()
    {
        if (!disposed)
        {
        Dispose(true);
        GC.SuppressFinalize(this);
        disposed = true;
        }
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
        //free managed ressources
        }
    // free other ressources
    }

    ~MyClass()
    {
        Dispose(false);
    }
}

It makes total sense the way the methods work. But now my question: Why do we need the base class IDisposable? In this code sample we define a method called Dispose(). As I read everywhere that method is part of IDisposable, but we have just defined that method within MyClass and this code would still work if we don't implement the base class IDisposable or am I wrong with this assumption?

I am not fully new to C# but there is still a lot for me to learn, so hopefully someone can lead me in the right direction here. I checked for another post with the same question, but couldn't find it, so if it does exist and it does answer my question please lead me there and I will delete this post.

15
  • 2
    IDisposable is not a [base] class. It is an interface. Why are any interfaces needed in C#? (IDisposable does no more no less than other interfaces.) Commented Jan 28, 2013 at 1:20
  • Thanks for the quick response. Well, since I still have much to learn about C#, please then answer the question you just asked back to me. Commented Jan 28, 2013 at 1:23
  • Thanks for the link, the sarcasm is a bit unnecessary in my opionion. I was not aware of the fact that there is such a great distincion between base classes and interfaces Commented Jan 28, 2013 at 1:28
  • In any case, an interface provides a Nominative Type (a type/contract that is known by a given name) without affecting the Class Hierarchy of the object. This allows objects - of different types - to be used in across the same interface; some interfaces, like IDisposable (or ISerializable) also establish various "rules and patterns" of use. See the respective documentation. Commented Jan 28, 2013 at 1:32
  • 1
    Can we PLEASE answer fewer duplicates? Commented Jan 28, 2013 at 1:54

4 Answers 4

9

You are right, as your destructor ~MyClass call Dispose, it seems there is no need for the interface IDisposable.

But Dispose is not called only by the destructor. You can call it yourself in the code when you want unmanaged resources to be disposed. It is needed because you don't know when the destructor is called (it is up to the garbage collector).

Finally, IDisposable.Dispose is called when you use a using.

using(MyDisposableClass myObject = new MyDisposableClass())
{
    // My Code
}

is equivalent to:

MyDisposableClass myObject = new MyDisposableClass();
try
{
    // My Code
}
finally
{
    myObject.Dispose();
}
Sign up to request clarification or add additional context in comments.

2 Comments

That is a great explanation, thanks for the quick clarification
You can't explicit call the C# class destructor either. It's first called when GC kicks in, as opposed to .Dispose() which is often called explicitly by user code.
2

The actual implementation of IDisposable.Dispose calls the base class implementation of Dispose(bool). Anyone who inherits from this class now has the following task should they also need to dispose:

public override Dispose(bool disposing)
{
    base.Dispose(disposing);
    //my disposal code
}

Using this well-recognised pattern allows inheritors to extend the disposal code without breaking the disposal of the base class.

Frequently, if you don't have unmanaged resources to dispose AND can afford to seal your class, you can simplify matters with the following code:

public sealed class SomeDisposable:IDisposable
{
    public void Dispose()
    {
       //just go ahead and clean up
       //because we're sealed, no-one can ever break
       //this code via inheritance
    }
    //~SomeDisposable()
    //{
    //   if this is being called then it will be called
    //   on all referenced and unrooted IDisposables too
    //   If everything is managed, that means we've got nothing
    //   left to clean up, so we can omit this Finalizer 
    //}
}

1 Comment

Thanks and +1 for the addition of sealed classes.
2

Implementing IDispose gives you a place to release resources that you "hold" like streams, handles or database-connections.

Dispose() is called from the garbage collector, basically asking the object: "if there is something that you no longer need, but I can't figure out; release it now; clean up!"

In a sense comparable to the destructor in for example C++

Difference is that the C++ destructor gets called immediately and Dispose() further in time.

In most cases you don't need to implement it. The GC is clever enough to figure out in 90% of the cases how to free up used resources.

But for example: releasing the memory used by a stream doesn't automatically close the stream and releasing a database-connection doesn't close it either.

Implementing Dispose allows you to close the file when your object is released:

internal class Something : IDisposable {
private Stream stream;

public void SomeMethod() {
    stream.Write("nskdns");
}

public void Dispose() {
    if (stream != null) {
        stream.Close();
    }
}

In addition: implementing IDispose gives you the opportunity to use the class inside a using statement:

public void Example() {
    using (var x = new Something())
    {
        x.SomeMethod();
    }
}

ensuring that x always will close the used stream when it's get free'd up by the GC.

I prefer however a dedicated Close() method on the class to allow an explicitly close of the stream instead of relying on the GC and calling Dispose()

Comments

1

It is used with the using block by the C# compiler.

1 Comment

While I'd not call this a "complete" answer, using (and more manual lifetime management via Dispose()) is the only reason for IDisposable .. so +1.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.