Piyush
Piyush

Reputation: 83

Writing our own Dispose method instead of using Idisposable

After going through a lot of articles on IDisposable, I got confused about its usage. All the articles explain what is it and how to implement it, but I want to understand what we will miss if we don't have it.

Here is an example of an class implementing IDisposable. Often the use of dispose is shown as disposing a database connection.

public class Test : IDisposable
{
    public Test()
    {
        DatabaseConnection databaseConnection = new DatabaseConnection();
    }

    public void Dispose()
    {
        if (this.databaseConnection != null)
        {
            this.databaseConnection.Dispose();
            this.databaseConnection = null;
        }
    }
}

Although Dispose() is implemented, inside the Dispose() method, the dispose property of databaseConnection is used to free the connection (this.databaseConnection.Dispose();).

My question is why do we need to implement IDisposable in this case? We can directly call this.databaseConnection.Dispose() and free the connection. Why implement IDisposable when internally it also calls the Dispose() method of the object?

Alternative to the approach of IDisposable, we can implement a method Release() to free the memory.

public class Test
{
    public Test()
    {
        DatabaseConnection databaseConnection = new DatabaseConnection();
    }

    public void Release()
    {
        if (this.databaseConnection != null)
        {
            this.databaseConnection.Dispose();
            this.databaseConnection = null;
        }
    }
}

What is the difference between these two approaches? Do we really need IDisposable? I am looking forward to a concrete explanation.

Upvotes: 8

Views: 2649

Answers (5)

Mike Chamberlain
Mike Chamberlain

Reputation: 42520

Managed objects will be disposed of automatically by garbage collection at some non-deterministic point in the future. However, when working with objects that may hold unmanaged resources (not under control of the CLR / garbage collection), the IDisposable interface should be implemented to provide a consistent and deterministic method of returning these resources to the operating system.

The interface only provides any real benefit when the object is used within the context of a using() { ... } block. Such a block tells the CLR to call the Dispose method when it hits the closing brace of the block. So no matter what happens within this block (short of some catastrophic system failure), your Dispose method is guaranteed to be called and your unmanaged resources freed.

For instance, in the code you provided, if an exception was thrown, then your Release() method may never get called, potentially leaving the connection open. However, when working with a disposable object within a using block, when the exception is thrown, the CLR will jump in and call your Dispose method before it throws the exception.

Upvotes: 0

FMM
FMM

Reputation: 4329

IDisposable is worth implementing, mostly, because it's idomatic in C#. Everybody knows what IDisposable does, and how to deal with an object that implements IDisposable. When you are releasing resources using something other than IDisposable.Dispose(), you're deviating from the generally-understood idiom.

This means that a maintainer doesn't have to know the ins and outs of your particular class to prevent leaking resources. This may even be you, in 6 months, when you've forgotten most of what you've done with this piece of code! All you need to know is that it implements IDisposable, which has a commonly-understood meaning.

Remember that IDisposable, mostly, is a signal to a developer, "Hey, I'm a class that holds references to unmanaged resources. You probably shouldn't wait on the garbage collector to clean me up." Note that this may be indirectly via composition (a class that implements IDisposable because it has private members that implement IDisposable). When a decent C# developer sees a class implementing IDisposable, they should immediately think "This object is special, and needs to be cleaned up when I'm done with it." There's nothing preventing you from writing a Release() method; it just means that you're more likely to accidentally leak resources because you're not using the idiomatic pattern.

Upvotes: 1

amit
amit

Reputation: 11

public class DotNetTips
{
    private void DoSomeOperation()
    {
        using (var con1 = new SqlConnection("First Connection String"),
                   con2 = new SqlConnection("Second Connection String"))
        {
            // Rest of the code goes here
        }
    }

    private void DoSomeOtherOperation()
    {
        using (SqlConnection con = new SqlConnection("Connection String"))
        using (SqlCommand cmd = new SqlCommand())
        {
            // Rest of the code goes here
        }
    }
}

A using statement is useful when we have to call the Dispose() method multiple times on different objects. Otherwise, we will have to call it on each object as:

if (con != null) con.Dispose();
if (cmd != null) cmd.Dispose();

Upvotes: 1

Jon Hanna
Jon Hanna

Reputation: 113372

  1. If your Release() worked correctly (it doesn't, but that's a different matter), then people would have to learn about it, and learn something else with another class, and so on.
  2. Your Release() could never be found programatically. It's possible to programatically call Dispose() when applicable with:

    if(obj is IDisposable)
      ((IDisposable)obj).Dispose();
    

While not often done, when it is done, it's vital.

It is sometimes useful to have a method like your Release() when it's possible someone might want to call it during object use. An example of this is Close() on Stream. Note here though that Stream.Dispose() still exists, and calls into Close().

Upvotes: 1

driis
driis

Reputation: 164341

You are right, using your Release method you would get the exact same effect, provided you always remember to call it.

The reason why you should use Dispose / IDisposable for this sort of thing is consistency. All .NET developers will know about the IDisposable pattern, and a class being IDisposable indicates that you should dispose of it, and do it using the Dispose method. In other words, using the IDisposable pattern immediately tells another developer, that he should release the resources held by the class, and he should do it by calling the Dispose method.

Another benefit of implementing IDisposable is the using block, which works on any IDisposable class:

using(var t = new Test())
{
    // use t
}

Using the above code will result in t being Dispose()ed at the end of the using block. It is syntactic sugar for a try...finally block, but it tends to make this kind of code more concise and easier to read and write.

Upvotes: 12

Related Questions