7

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.

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
Mehmet Ataş
  • 11,081
  • 6
  • 51
  • 78

8 Answers8

10

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();
}
Nikhil Agrawal
  • 47,018
  • 22
  • 121
  • 208
4

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.

Anders Arpi
  • 8,277
  • 3
  • 33
  • 49
  • What if constuctor or process method throws exception? – Mehmet Ataş Nov 09 '12 at 12:09
  • That is the entire point of the `using` clause. It will always dispose of the object constructed within it **even if an exception occurs**. It's basically like using a try/finally, except less writing. I even said so in this very answer. – Anders Arpi Nov 09 '12 at 12:45
  • 1
    I know that but what I am trying to learn is how people handle exceptions thrown by Disposable objects. A try-catch-finally or a try-catch surrounding using block or something else. – Mehmet Ataş Nov 09 '12 at 13:01
  • If you have a disposable object and want to handle exceptions in a specific way, I'd recommend using a try/catch/finally. In the finally - dispose it, in the catch - handle exceptions. But of course it depends a bit on if you can pinpoint the place in your code where the exception should occur, in that case you might want to use a `using` and then surround the part that might fail with a try/catch. – Anders Arpi Nov 09 '12 at 13:17
3

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();
  }
Habib
  • 219,104
  • 29
  • 407
  • 436
2
using (Disposable dispObj = new Disposable())
    {
        dispObj.Process();
    }
}
Aghilas Yakoub
  • 28,516
  • 5
  • 46
  • 51
1

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

Vinoth
  • 2,419
  • 2
  • 19
  • 34
  • You should also implement `IDisposable` to call `Dispose` on any composed objects (whether in member fields or properties) that implement `IDisposable` themselves. – Richard Aug 01 '12 at 09:32
0

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

Chris Mantle
  • 6,595
  • 3
  • 34
  • 48
0
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
}
dantix
  • 745
  • 1
  • 5
  • 14
  • What if "some logic" or "new FileStream" method throws exception? – Mehmet Ataş Nov 09 '12 at 12:11
  • If "new FileStream" throws exception it's "okay". Object wasn't created, so there is nothing to dispose. If "some logic" throws exception, dispose will called from finally. – dantix Nov 10 '12 at 08:52
  • Ok I know, but how about exception handling? This question is: Would you prefer surrounding using with a try-catch or use a try-catch-finally or something different? – Mehmet Ataş Nov 10 '12 at 10:37
0

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.

aaaantoine
  • 900
  • 8
  • 19
  • One problem with the first approach is that if the `Dispose` method invoked by `using` throws an exception (perhaps it was trying to close a file on an ejected USB drive) there's no way to know whether an exception occurred within the `using` block itself. In cases where `Dispose` might possibly throw an exception, it may be good to have a `catch` within it to ensure that exceptions that get thrown there won't get overwritten. – supercat Dec 29 '14 at 19:02
  • Further reading on the concern raised by @supercat: [Intercepting an exception inside IDisposable.Dispose()](http://stackoverflow.com/questions/220234/intercepting-an-exception-inside-idisposable-dispose) [Should you implement IDisposable.Dispose() so that it never throws?](http://stackoverflow.com/questions/220234/intercepting-an-exception-inside-idisposable-dispose) – aaaantoine Dec 30 '14 at 15:01