Does Dispose Still Get Called When Exception Is Thrown Inside of a Using Statement

Does Dispose still get called when exception is thrown inside of a using statement?

Yes, using wraps your code in a try/finally block where the finally portion will call Dispose() if it exists. It won't, however, call Close() directly as it only checks for the IDisposable interface being implemented and hence the Dispose() method.

See also:

  • Intercepting an exception inside IDisposable.Dispose
  • What is the proper way to ensure a SQL connection is closed when an exception is thrown?
  • C# "Using" Syntax
  • C# USING keyword - when and when not to use it?
  • 'using' statement vs 'try finally'
  • What is the C# Using block and why should I use it?
  • Disposable Using Pattern
  • Does End Using close an open SQL Connection

If an exception occurs inside a using block, is the Dispose method called?

Yes it will get called.

using translates into try-finally block, so even in case of recoverable exception Dispose gets called.

See: using statement C#

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.

Consider SqlConnection which implements IDisposable interface, so the following:

using (SqlConnection conn = new SqlConnection("connectionstring"))
{
//some work
}

Would get translated into

{
SqlConnection conn = new SqlConnection("connectionstring");
try
{
//somework
}
finally
{
if (conn != null)
((IDisposable)conn).Dispose(); //conn.Dispose();
}
}

If an Exception happens within a using statement does the object still get disposed?

Yes, they will.

using(SPWeb spWeb = spSite.OpenWeb())
{
// Some Code
}

is equivalent to

{
SPWeb spWeb = spSite.OpenWeb();
try
{

// Some Code
}
finally
{
if (spWeb != null)
{
spWeb.Dispose();
}
}
}

Edit

After answering this question, I wrote a more in depth post about the IDisposable and Using construct in my blog.

Are resources disposed even if an exception is thrown in a using block?

The resources defined with the using statement were disposed, this is the main reason what using is good for.

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.

http://msdn.microsoft.com/en-us/library/yh598w02%28v=VS.100%29.aspx

IDisposable.Dispose is never called after exception in using block

Environment.Exit will terminate the program

If Exit is called from a try or catch block, the code in any finally
block does not execute. If the return statement is used, the code in
the finally block does execute.

using (var x = new Disposable())
{
throw new Exception("asdfsdf");
}

will be converted to

Disposable x = new Disposable();
try
{
throw new Exception("asdfsdf");
}
finally
{
if (x != null)
x.Dispose();
}

Does using statement always dispose the object?

Yes, that's the whole point. It compiles down to:

SomeDisposableType obj = new SomeDisposableType();
try
{
// use obj
}
finally
{
if (obj != null)
((IDisposable)obj).Dispose();
}

Be careful about your terminology here; the object itself is not deallocated. The Dispose() method is called and, typically, unmanaged resources are released.

Using statement with try catch. What happens to instance from using statement?

You can think of using as a short-hand for try-finally. Hence your code is equivalent to:

IDatabaseConnectivityObject databaseConnectivityObject = new DbProviderFactoryConnectionBasicResponse();
try
{
try
{
Foo();
}
catch(ArgumentNullException e)
{
throw;
}
}
finally
{
if(databaseConnectivityObject != null)//this test is often optimised away
databaseConnectivityObject.Dispose()
}

Looked at this way, you can see that the Dispose() will indeed be called if the exception throws, because the try-finally is outside of the try-catch.

This is precisely why we use using.

Will be Disposable resource disposed if try/catch is used inside using statement?

In your case the exception is catched right inside the using and the dispose is executed when you leave the using block.

But even if you put the using block outside the try catch and an exception is thrown, the dispose will be called.

public static void LogError(string error, string message)
{
try
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["connStringWeb"]))
using (SqlCommand cmd = new SqlCommand("INSERT INTO errorLogTable (errorTime, errorType, error) VALUES(@errorTime, @errorText, @errorMsg)"))
{
cmd.CommandTimeout = 300;
cmd.Connection = conn;
cmd.Prepare();
cmd.Parameters.AddWithValue("@errorTime", DateTime.Now);
cmd.Parameters.AddWithValue("@errorText", error);
cmd.Parameters.AddWithValue("@errorMsg", message);

conn.Open();
int i = cmd.ExecuteNonQuery();
}
}
catch {}
}

Unhandled Exception with Using statement

using translates into try-finally block, it doesn't have catch, so you are misunderstanding the article. It will not catch any exception, It will only make sure to dispose the object in case of an exception.

In your case since it a FileNotFound exception, your object will not be initialized.

Your code would translate into something like:

{
TextReader sv = null;
try
{
sv = File.OpenText(@"sv\.sv");
char[] k = { ':' };
lastWsp = sv.ReadLine().Split(k)[1];
}
finally
{

if(sv != null)
sv.Dispose();
}
}

In the above code in case of exception, it will try to dispose your object sv. But the exception will remain unhandled .

Since in your code, the exception is FileNotFound your object sv will remain null (uninitialized) and hence there will be no reason to call Dispose. But imagine if you have valid file path, and you get an exception at sv.ReadLine().Split(k)[1]; then it will dispose your TextReader sv, and that exception will propagate up in the hierarchy because there is no catch block.

What is the purpose of the using statement?

if I understand correctly, the using statement works like a try/finally

Correct.

so I would expect that if an exception occurs in a using statement, it should not crash the program.

Incorrect.

Neither try/finally nor using statements swallow exceptions - if you don't catch the exception, it will propagate up. If it's uncaught, it will usually terminate the process. (There are a few cases where it won't, based on which thread it's in and how the CLR is configured, but that's a different matter.)

But then I wonder what is the purpose of the using statement.

To make it simpler to write code that needs to dispose of resources. That's all. If we didn't have using statements, we'd have a lot of try/finally blocks which just called Dispose... and that would be considerably uglier. (Been there, done that - that was Java until Java 7 introduced the try-with-resources statement.)



Related Topics



Leave a reply



Submit