Mehmet Ataş
Mehmet Ataş

Reputation: 11559

How to handle exceptions thrown by disposable objects?

What is the best way for using Disposable objects, assuming Constructor and Process methods may throw exception? I generally prefer one of below implementations.

  1. try-catch surrounding using block

    try
    {
        using (Disposable dispObj = new Disposable())
        {
            dispObj.Process();
        }
    }
    catch (Exception ex)
    {
        // Do something
    }
    
  2. try-catch-finally block.

    Disposable dispObj2 = null;
    try
    {
        dispObj2 = new Disposable();
        dispObj2.Process();
    }
    catch (Exception ex)
    {
        // Do something
    }
    finally
    {
        if (dispObj2 != null)
        {
            dispObj2.Dispose();
        }
    }
    

UPDATE:

Again: "assuming Constuctor and Process methods may throw exception". I really do not understand why did nobody care about exceptions in their answers.

Upvotes: 7

Views: 2671

Answers (8)

aaaantoine
aaaantoine

Reputation: 900

Method #1 which you have proposed is likely the most succinct way to achieve what you want.

The surrounding try...catch block should catch any exceptions thrown, including those thrown by the constructor. If the exception occurs while the disposable object is in use (inside the using block), the object will also be disposed before catch takes over.

Method #2 takes a different execution path from Method #1. Note that according to C# Reference, Method #1 literally compiles as if the following were written:

try
{
    {
        Disposable dispObj = new Disposable();
        try
        {
            dispObj.Process();
        }
        finally
        {
            if (dispObj != null)
                ((IDisposable)dispObj).Dispose();
        }
    }
}
catch (Exception ex)
{
    // Do something
}

So, scopes between the two methods are different. I would prefer Method #1 when possible, because of scope concerns and also because it's easier to read.

Upvotes: 0

Habib
Habib

Reputation: 223287

using statement uses try - finally in the background and works only with object which implements IDisposable. You don't have to use try catch with using. Look at the following example (From MSDN - using statement).

using (Font font1 = new Font("Arial", 10.0f)) 
{
    byte charset = font1.GdiCharSet;
}

the above code is same as:

Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }

Upvotes: 3

Nikhil Agrawal
Nikhil Agrawal

Reputation: 48568

using is good. It has an inbuilt try-finally block. If exception occurs, dispose method is called automatically.

This is fine

using (Disposable dispObj = new Disposable())
{
    dispObj.Process();
}

Upvotes: 10

dantix
dantix

Reputation: 745

using (IDisposable disp = new IDisposable())
{
   //some logic here
}

This code will be translated in something like this:

IDisposable disp = new IDisposable();

try
{
  //some logic here
}
finally
{
  if (disp != null)
     ((IDisposable)disp).Dispose();
}

Code in block "finally" executes always, so it's giving you possibility to throw exceptions, making returns from using block without any doubts that Dispose wouldn't be called.

But you should be careful with using and object initializers.

using (var fs = new FileStream(@"C:\blabla", FileMode.Open) { Position = pos })
{
    //some logic here
}

As you can see from here property Position can throw exceptions. And problem is that object will be created and this will be done out of try block, so there could be a memory leak. Right way to this

using (var fs = new FileStream(@"C:\blabla", FileMode.Open))
{
    fs.Position = pos;
    //some logic here
}

Upvotes: 0

Vinoth
Vinoth

Reputation: 2439

Classes that implement the IDisposable interface typically use resources that cannot be cleaned up by the .NET framework garbage collector. Calling the IDisposable.Dispose() method executes code that explicitly releases a precious resource back into the world. A prime example of a class that implements the IDisposable interface is the SqlConnection class. A SqlConnection class uses a Microsoft SQL Server database connection. Because SQL Server supports a limited number of connections, it is important to release a connection as quickly as possible. Typically, you do not call the Dispose() method directly. Typically, you take advantage of a Using statement in your code like you mentioned in your code

Upvotes: 1

Chris Mantle
Chris Mantle

Reputation: 6683

Where possible, you should use a using block. It will guarantee that Dispose is called on your object. Doing it manually is error-prone.

Upvotes: 0

Anders Arpi
Anders Arpi

Reputation: 8397

Do it like this:

using (Disposable dispObj = new Disposable())
{
    dispObj.Process();
}

Disposable objects are always disposed when they go out of scope of the using clause, even if it's by an exception.

And don't use an empty catch {}, completely pointless.

Upvotes: 4

Aghilas Yakoub
Aghilas Yakoub

Reputation: 28980

using (Disposable dispObj = new Disposable())
    {
        dispObj.Process();
    }
}

Upvotes: 2

Related Questions