views:

731

answers:

7

Assume the following code:

using (SqlConnection conn = new SqlConnection(connectionString))
{
   ...
   using (SqlCommand comm = new SqlCommand(...))
   {
      .. do stuff ..
      if(condition) Response.Redirect("somepage.aspx");

   }
}

Will the Response.Redirect() exit from the using blocks cause it to dispose all connections?

Or, alternatively, is there any way to exit a using block that won't cause disposal?

EDIT: I don't want to exit without disposal. I want to be aware of any pitfalls that would cause it not to work. -- Barring crashes of course, but then I'm pretty sure all objects are disposed --the hard way-- in that situation

I've accepted an answer, which essentially says "I don't know" but it's a very well researched "I don't know"

For the mean time, I'm going to assume that Response.Redirect aborts the using statement and code with that in mind. -- Until proven otherwise.

+2  A: 

Q: Or, alternatively, is there any way to exit a using block that won't cause disposal?

A: None.

See this for more info: http://stackoverflow.com/questions/149609/c-using-syntax#149643

jop
A: 

All using statements are scope based. So no matter how you exit the function everyone that was stack based at that point is cleaned up from the using. Exceptions, returns, etc.

I don't know of any way to prevent one from firing even if you wanted to for some reason.

Jason Short
I don't want to prevent disposal. I want to be aware of any Gotchas.
chris
+2  A: 

Response.Redirect terminates the server-side execution.

In the normal course of execution, exiting a using-block triggers object disposal. Exceptions to this rule may occur e.g. when the process is shut down, when the computer is shut down, when a thread is aborted, etc. But not in the normal course of execution.

Look into Server.Transfer. It may help you accomplish your goals.

Justice
A: 

Why would you like to exit an using block without the disposal? That's not the idea of the using block.

Do not use it if you like to, but I wouldn't recommend it.

Leandro López
A: 

What's wrong with:

using(SqlCommand comm = new SqlCommand(...))
{
...
if(condition)
{

//We have decided this is true so we don't need the using any more
//Disposal Code

break;
//or continue; if that's better
}
//Code that executes in the case of "if" not true.
}

Response.Redirect(page);"

?

A break does not save your from disposal.
jop
But I explicitly leave a comment point to indicate where the disposal code should go.
Oh, I see what you mean. What I was trying to do was not have him Redirect unless he had finished with the using block. Obvously he doesn't want to redirect until the Disposal has taken place. I was assuming he still might want to Redirect after he'd finished.
So set a flag, and redirect after the using block.
chris
Yeah that was my other thought but I thought the example was enough to push that way. Just trying to help out. Maybe won't bother in future.
But thanks for the back up vote anyway... ;)
+2  A: 

From http://msdn.microsoft.com/en-us/library/aa973248.aspx

Calling Response.Redirect WILL NOT execute the finally block. Therefore, before any redirection or transfer of processing can occur, you must dispose of the objects.

Yes, it does not directly address the Using statement, but it is a common enough programming practice to be aware of. Also, that article refers to SharePoint, but as SP is built on ASP.NET 2.0, I think it is still relevant.

Jason Z
+3  A: 

From http://msdn.microsoft.com/en-us/library/aa973248.aspx and http://msdn.microsoft.com/en-us/magazine/cc163298.aspx:

Calling Response.Redirect WILL NOT execute the finally block (and language-specific keywords like the C# "using" statement). Therefore, before any redirection or transfer of processing can occur, you must dispose of the objects.

But from http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx:

When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block. When this exception is raised, the runtime executes all the finally blocks before ending the thread. Since the thread can do an unbounded computation in the finally blocks, or call Thread..::.ResetAbort to cancel the abort, there is no guarantee that the thread will ever end. If you want to wait until the aborted thread has ended, you can call the Thread..::.Join method. Join is a blocking call that does not return until the thread actually stops executing.

Sounds like a test is in order...

Even Mien
As such I would recommend doing the Page.Transfer outside of the using block. Refactor your code to test a condition flag after the using block has completed.
Kimoz