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.

Community
  • 1
  • 1
philkark
  • 2,417
  • 7
  • 38
  • 59
  • 2
    **IDisposable is not a [base] class**. It is an [interface](http://msdn.microsoft.com/en-us/library/vstudio/ms173156.aspx). Why are *any* interfaces needed in C#? (IDisposable does no more no less than other interfaces.) –  Jan 28 '13 at 01: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. – philkark Jan 28 '13 at 01: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 – philkark Jan 28 '13 at 01: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. –  Jan 28 '13 at 01:32
  • 1
    Can we PLEASE answer fewer duplicates? – John Saunders Jan 28 '13 at 01:54
  • @JohnSaunders Please read my question. I have been looking for an answer to MY question and it looks like you do not understand what exactly my problem is. It is not the way IDisposable is used, but the the actual reason why. The simple answer: There is a big difference between interfaces and base classes, which I did not know. – philkark Jan 28 '13 at 02:01
  • No, the problem is that you don't understand what IDisposable is about. It has nothing to do with freeing memory. First, I suggest you go read the question and answers I linked as a duplicate, then come back if you have further questions. This question is maybe the hundredth duplicate of this just in the month of January, 2013. – John Saunders Jan 28 '13 at 02:05
  • @JohnSaunders I read about 6 posts on stackoverflow (including your suggestion of a duplicate) about IDisposable before posting this question. None of them helped me. Funnily the way Cédric Bignon phrased it in my accepted answer did help me, so please don't make it impossible for people who don't know C# as well as you, to get their exact questions answered. I understand duplicates are not nice here, but in my case I don't see the duplication case. – philkark Jan 28 '13 at 02:08
  • (I didn't know I _had_ a post on IDisposable. Got a link to it?) – John Saunders Jan 28 '13 at 02:10
  • Sorry. Here's a better suggestion: go read those articles, especially the one I linked. Don't read them to get an answer to your question. Read them to understand what IDispoable is about. Among other things, it's not a base class, and it has nothing to do with memory allocation. Once you understand those things, if there are other things you don't understand, then please ask. But your question, as written is based on several misunderstandings and should be deleted. – John Saunders Jan 28 '13 at 02:11
  • See my edit. In my opinion, your unfriendly phrasing makes stackoverflow much less pleasant to use. So far it only looks like only you think this is a duplicate. People who are not as skilled as you should have their opportunity to ask their questions and people like you make this quite impossible. – philkark Jan 28 '13 at 02:14
  • You did ask your question. I pointed you to where to learn the answer. You're fortunate that someone was able to get past your misunderstanding and find what you really needed to know. But it won't help anyone else, so should be closed and deleted. As to you, you should take my unfriendly advice: learn what you can from the linked articles, then come back with any specific questions, once you understand enough to ask them. – John Saunders Jan 28 '13 at 02:16
  • Well, it turns out that three answers here were very helpful to me (none on any other page). Yes, I did not understand it well enough, you however cannot know that noone has the same problem as me, it will not be uncommon to confuse IDisposable as a base class. – philkark Jan 28 '13 at 02:21
  • I've been on this site for three years and that's not a very common misconception. Most people have read something like "[Interface or abstract class?](http://stackoverflow.com/questions/1165332/interface-or-abstract-class)" first. As such, their confusion is over the specifics of IDisposable, not about base classes or memory management. – John Saunders Jan 28 '13 at 04:47
  • It would be fair to change your title to "Is the IDisposable Interface an Abstract Base Class?" or "Is the IDisposable Interface used for Memory Management?" It might be fair, but it would not be friendly. – John Saunders Jan 28 '13 at 04:48

4 Answers4

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();
}
Cédric Bignon
  • 12,892
  • 3
  • 39
  • 51
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 
    //}
}
spender
  • 117,338
  • 33
  • 229
  • 351
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()

lboshuizen
  • 2,746
  • 17
  • 20
1

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

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • 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. –  Jan 28 '13 at 01:29