Using statement vs. IDisposable.Dispose()

C#.Netvb.netUsingIdisposable

C# Problem Overview


It has been my understanding that the using statement in .NET calls an IDisposable object's Dispose() method once the code exits the block.

Does the using statement do anything else? If not, it would seem that the following two code samples achieve the exact same thing:

Using Con as New Connection()
	Con.Open()
	'do whatever '
End Using

Dim Con as New Connection()
Con.Open()
'do whatever '
Con.Dispose()

I will give the best answer to whoever confirms that I am correct or points out that I am wrong and explains why. Keep in mind that I am aware that certain classes can do different things in their Dispose() methods. This question is about whether or not the using statement achieves the exact same result as calling an object's Dispose() method.

C# Solutions


Solution 1 - C#

using is basically the equivalent of:

try
{
  // code
}
finally
{
  obj.Dispose();
}

So it also has the benefit of calling Dispose() even if an unhandled exception is thrown in the code within the block.

Solution 2 - C#

As Brian Warshaw stated in here it's simply an implementation of try and finally block to make sure object is disposed. Adding to his answer, using block also makes sure that the object is disposed even if you return inside using scope.

I was once curious about this myself and tested it out using the following approach:

Custom IDisposable test class and Main

private class DisposableTest : IDisposable
{
    public string Name { get; set; }

    public void Dispose() { Console.WriteLine("{0}.Dispose() is called !", Name); }
}

public static void Main(string[] args)
{
    try
    {
        UsingReturnTest();
        UsingExceptionTest();                
    }
    catch { }

    try
    {
        DisposeReturnTest();
        DisposeExceptionTest();                
    }
    catch { }

    DisposeExtraTest();

    Console.ReadLine();
}        

Test cases implementation

private static string UsingReturnTest()
{
    using (DisposableTest usingReturn = new DisposableTest() { Name = "UsingReturn" })
    {
        return usingReturn.Name;
    }
}

private static void UsingExceptionTest()
{
    using (DisposableTest usingException = new DisposableTest() { Name = "UsingException" })
    {
        int x = int.Parse("NaN");
    }
}

private static string DisposeReturnTest()
{        
    DisposableTest disposeReturn = new DisposableTest() { Name = "DisposeReturn" };
    return disposeReturn.Name;
    disposeReturn.Dispose(); // # IDE Warning; Unreachable code detected
}

private static void DisposeExceptionTest()
{
    DisposableTest disposeException = new DisposableTest() { Name = "DisposeException" };
    int x = int.Parse("NaN");
    disposeException.Dispose();
}

private static void DisposeExtraTest()
{
    DisposableTest disposeExtra = null;
    try
    {
        disposeExtra = new DisposableTest() { Name = "DisposeExtra" };
        return;
    }
    catch { }
    finally
    {
        if (disposeExtra != null) { disposeExtra.Dispose(); }
    }
}

And the output is:

  • UsingReturn.Dispose() is called !
  • UsingException.Dispose() is called !
  • DisposeExtra.Dispose() is called !

Solution 3 - C#

//preceeding code
using (con = new Connection()) {
    con.Open()
    //do whatever
}
//following code

is equivalent to the following (note the limited scope for con):

//preceeding code
{
    var con = new Connection();
    try {
        con.Open()
        //do whatever
    } finally {
        if (con != null) con.Dispose();
    }
}
//following code

This is described here: http://msdn.microsoft.com/en-us/library/yh598w02.aspx

> The using statement ensures that Dispose is called even if an > exception occurs while you are calling methods on the object. You can > achieve the same result by putting the object inside a try block and > then calling Dispose in a finally block; in fact, this is how the > using statement is translated by the compiler.

Solution 4 - C#

A using statement is clearer and more concise than a try...finally{Dispose()} construct, and should be used in nearly all cases where one does not want to allow a block to exit without Dispose being called. The only common situations where "manual" disposal would be better would be when:

  1. A method calls a factory method which returns something that may or may not implement IDisposable, but which should be Disposed if it does (a scenario which occurs with non-generic IEnumerable.GetEnumerator()). Well-designed factory interfaces should either return a type that implements IDisposable (perhaps with a do-nothing implementation, as is typically the case of IEnumerator<T>) or else specify callers are not expected to Dispose the returned object. Unfortunately, some interfaces like non-generic IEnumerable satisfy neither criterion. Note that one cannot very well use using in such cases, since it only works with storage locations whose declared type implements IDisposable.
  2. The IDisposable object is expected to live even after the block is exited (as is often the case when setting an IDisposable field, or returning an IDisposable from a factory method).
Note that when returning an IDisposable from a factory method, one should use something like the following:
bool ok = false;
DisposableClass myThing;
try
{
myThing = new DisposableClass();
...
ok = true;
return myThing;
}
finally
{
if (!ok)
{
if (myThing != null)
myThing.Dispose();
}
}
to ensure that myThing will get Disposed if it doesn't get returned. I wish there was a way to employ using along with some "cancel Dispose" method, but no such thing exists.

Solution 5 - C#

The difference between the two is that, if an Exception is thrown in

Con.Open()
'do whatever

Con.Dispose will not be called.

I'm not up on VB syntax, but in C#, the equivalent code would be

try
{
    con = new Connection();
    // Do whatever
}
finally
{
    if (con != null) con.Dispose();
}

Solution 6 - C#

The using block makes sure that Dispose() is called if an exception is thrown.

Your second sample does not do that.

If Con.Open() threw an exception, in the first case you are guaranteed that Con.Dispose() is called. In the second case, the exception propagates up and Con.Dispose() will not be called.

Solution 7 - C#

The using statement guarantees that the object is disposed in the event an exception is thrown. It's the equivalent of calling dispose in a finally block.

Solution 8 - C#

Using wraps the enclosed block in a try/finally that calls Dispose in the finally block. This ensures that Dispose will be called even if an exception occurs.

You should use using in almost all cases, for safety reasons

Solution 9 - C#

If memory serves, using is a guarantee that an object is disposed of regardless of how the block of code it surrounds exits it. It does this by surrounding the block in a try...finally block, and checking the used variable for nullness, and then disposing of it if it is not null. If an exception was thrown, it's allowed to bubble up the stack. Aside from that, all it does is guarantee disposal of non-null disposable objects.

try
{
  var myDisposable = new DisposableObject();
  myDisposable.DoSomething();
}
finally
{
  if (myDisposable != null)
    ((IDisposable)myDisposable).Dispose();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionoscilatingcretinView Question on Stackoverflow
Solution 1 - C#Brian WarshawView Answer on Stackoverflow
Solution 2 - C#Saro TaşciyanView Answer on Stackoverflow
Solution 3 - C#hatchet - done with SOverflowView Answer on Stackoverflow
Solution 4 - C#supercatView Answer on Stackoverflow
Solution 5 - C#Eric J.View Answer on Stackoverflow
Solution 6 - C#jglouieView Answer on Stackoverflow
Solution 7 - C#jrummellView Answer on Stackoverflow
Solution 8 - C#Panagiotis KanavosView Answer on Stackoverflow
Solution 9 - C#Mike HoferView Answer on Stackoverflow