What exactly is IDisposable needed for?

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.


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

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 
    //}
}

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()

链接地址: http://www.djcxy.com/p/54470.html

上一篇: 一次性使用和管理资源

下一篇: IDisposable究竟需要什么?