Reputation: 11559
What is the best way for using Disposable objects, assuming Constructor and Process methods may throw exception? I generally prefer one of below implementations.
try-catch surrounding using block
try
{
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
}
catch (Exception ex)
{
// Do something
}
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
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
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
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
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
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
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
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
Reputation: 28980
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
}
Upvotes: 2