What is the difference between try-finally and try-catch-throw? - c#

So, I understand from this question that finally blocks can be used to execute code even if an Exception occurs and even if the Exception is uncaught and allowed to propagate up.
I understand from this question that in C#, the throw keyword can be used alone (with no arguments) in a catch block to allow the caught Exception to continue propagating up without even resetting the stack trace.
My question, then, is what is the difference between THESE two blocks:
/* example 1 */
try { /* try stuff */ }
finally { /* finally/catch stuff */ }
/* example 2 */
try { /* try stuff */ }
catch { /* finally/catch stuff */ throw; }
Don't both run the stuff the try stuff, then run the finally/catch stuff, then allow the thrown Exception to propogate up with the same stack trace?

In
try { /* try stuff */ }
catch { /* finally/catch stuff */ throw; }
the finally stuff won't run when there is no error.
A finally{} block is used for cleanup, your suggestion would litter valuable resources.
You really missed the point here, only catch is about handling errors (optionally in stages). A finally block is about resource management and only related to exceptions in the sense that it will execute despite of any exceptions having occurred.

Think of it like this...
try
{
//do some stuff
}
catch
{
//do some stuff if there was an exception
//maybe some cleanup, maybe rethrow exception
}
finally
{
//always do this stuff exception or not
}

catch runs only if content of try throws an error, finally runs always after try and/or catch.

The difference is that the finally block is always executed both if you have an exception or not, instead the catch block is executed only if you have an exception

A finally will run regardless as to whether your code throws an exception or not, but it is my understanding (i could be wrong) that it may not run if you re-throw in a catch which is in turn not handled. The finally is useful when you need to tidy up regardless of whether an error occurred or not, such as disposing connections.
The second example would only have code run in the catch, or if the code doesn't throw and exception. In which case I would remove the try catch and let it bubble up and have the try catch higher up

Related

Exception Handling within Exception Handling

What is the best practice for exception handling within exception handling?
I find myself working on an existing C# (Framework 4.0) system that uses custom objects within the catch and finally blocks throughout most of the Application Server tier of the system.
Consider the following snipped version of a method in this codebase:
public void DoSomeStuff(string sGUID)
{
try
{
// Foo
}
catch (Exception oEx)
{
oExceptions.Add(oEx);
if (oDBConn.NumberOfActiveTrans > 0)
{
oDBConn.Rollback();
}
}
finally
{
oDBConn.DeleteLocksByGUID(sGUID);
}
}
I might be being overly paranoid, but I find myself very worried about possible unhandled exceptions that may occur with these.
As such, would something like the following updated version be an acceptable practice or is there a better way to accomplish the same thing?
public void DoSomeStuff(string sGUID)
{
try
{
// Foo
}
catch (Exception oEx)
{
oExceptions.Add(oEx);
try
{
if (oDBConn.NumberOfActiveTrans > 0)
{
oDBConn.Rollback();
}
}
catch (Exception oEEx)
{
oExceptions.Add(oEEx);
}
}
finally
{
try
{
oDBConn.DeleteLocksByGUID(sGUID);
}
catch (Exception oFEx)
{
oExceptions.Add(oFEx);
}
}
}
I personally wouldn't add a try catch block in the finally, then it can be an endless chain. Usually you shouldn't have complicated stuff in the finally and in any case unexpected exception should be caught in the caller.
Edit: looking a bit closer to the code, I don't see why the code in the finally shouldn't be in the try block.
I might be being overly paranoid, but I find myself very worried about
possible unhandled exceptions that may occur with these.
Don't panic. If there is an error in the db layer try catch it there.
The most dangerous thing in the original code is that if it fails and the transaction rollback fails, the only error rethrown will be the one from rolling back the transaction. You'll never know what the original exception was that caused you to have to roll back the transaction. That's the one that you probably care most about.
If you want to be paranoid, log the failure of the transaction rollback. But what matters is the previous exception that got you to that point. That should either be logged or rethrown depending on the expectation of the caller.

What is the finally block for compared to just writing code after the try statement?

In other words, how are these two different?
try
{
// Something that can throw an error
}
catch
{
// Handle the error
}
finally
{
// Something that runs after the try statement
}
vs.
try
{
// Something that can throw an error
}
catch
{
// Handle the error
}
// Something that runs after the try statement
finally block always executes.
You can be sure, that this block will be executed no matter what.
Literally it is something like:
Try something, catch some exceptions(if told to and if they are there) and execute the
finally block finally.
If there is a break in the try block or an exception, it may cause the program to halt. In cases like these code that is mandarory to be executed, like closing open connections and returning items to the connection pools are writen in the finally block. The finally block ensures that the code written inside it will be executed.
If you only ever use general catches (i.e. catch without args or catch(Exception ex)), whether to put code in finally or after try/catch is basically a stylistic choice, as both a finally block and code after a try/catch will execute in any situation (barring deliberate escape mechanisms such as return).
However, if you use a narrow catch, and the exception isn't caught, what will happen is the finally block will still execute, however the code after the try/catch won't.

Is finally block in C# a must?

What is the difference between 2 conditions? Every time when method1 or method2 runs, there should be a code block that is required to run. It seems to me that 2 method are the same.
// example method1
void Method1(void)
{
try
{
// do something
}
catch (Exception ex)
{
// do something
}
finally
{
// do something whenever method1 runs
}
}
// example method2
void Method2(void)
{
try
{
// do something
}
catch (Exception ex)
{
// do something
}
// do something whenever method2 runs
}
Finally block seems to be unnecessary for me.
In your first example, you could re-throw the exception and the code inside the finally would still run. This would not be possible in the second example.
If you choose not to re-throw the exception, then yes there is little difference. However, this is considered bad form - very rarely should you need to consume an exception that you cannot explicitly handle.
It is a keyword to help you with code execution flow. When you throw an exception the execution flow of the code is affected (like using return), the finally keyword allows you to express that when an exception occurs (or you return from a try) you still want execution to do something as it's leaving.
To answer the question facetiously, it is a must when you need it and not when you don't.
Further Reading
To be on the safe side, before you attempt to start making use of this keyword, please read the documentation for it:
http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx
And the exception handling keywords in general:
http://msdn.microsoft.com/en-us/library/s7fekhdy.aspx
Examples
Catch an exception to do something with it, then re-throw it. Use finally to call any tidy-up code:
try
{
OpenConnectionToDatabase();
// something likely to fail
}
catch (Exception ex)
{
Log(ex);
throw;
// throw ex; // also works but behaves differently
}
// Not specifying an exception parameter also works, but you don't get exception details.
//catch (Exception)
//{
// Log("Something went wrong);
// throw;
//}
finally
{
CloseConnectionToDatabase();
}
Don't register any interest in catching exceptions, but use finally to tidy-up code:
try
{
OpenConnectionToDatabase();
// something likely to fail
}
finally
{
CloseConnectionToDatabase();
}
Return from your try because it looks nicely formatted, but still use finally to tidy-up code:
try
{
OpenConnectionToDatabase();
return 42;
}
finally
{
CloseConnectionToDatabase();
}
As you know the code written inside the finally block always runs.
Please have a look onto the following point written below, it will clear your all confusion.
Finally is used for Resource management. Mainly for releasing an resources. It always runs independent upon the Exception.
As we know catch is used for handle an exception, but sometimes it fails to handle to an External exception. Then the finally block is used to handle that exception to perform the operation.
The code in the finally block will run anyway after the try-catch, it is very usefull for clean up.
try
{
// open resources
}
catch (Exception ex)
{
// something bad happened
}
finally
{
// close resources that are still opened
}
This will behave very differently depending on whether you return from the try, for example. Also - the finally will run even if the catch throws an exception (or re-throws the original exception), which will not happen without the finally.
So: it isn't required, but it will behave differently. So if you want the code to happen, put it in the finally.
In many ways, try/finally is much more common than try/catch or try/catch/finally.
You do not absolutely have to have the finally block, however, having it guarantees that the code within it will always run (unless there is an exception in the finally!).
Consider the following:
void Method2(void)
{
try
{
// do something
}
catch (Exception ex)
{
// do something
throw;
}
// do something whenever method2 runs
}
the code after the try/catch will not execute if an exception is thrown. Additionally, if the code within the catch block has an error that causes an exception (such as your logging throwing an unexpected exception) the code that should have been in the finally will not run, leaving and cleanup undone.
Also a return statement will cause that code to not be run, while the finally will still be executed (also, here you can see that the catch can be skipped too, allowing any exceptions to propogate upwards - AFTER executing the finally):
void Method2(void)
{
try
{
// do something
return
}
finally
{
// do something whenever method2 runs
}
}
Whenever you have cleanup code that must be run at the end of a method, use finally (or if your objects implement IDisposable use the using statement).
The finally block ensures that any code within it ALWAYS gets executed so if you have a return statement inside your try block or rethrow an exception within your catch block, the code inside the finally block will always execute.
It is a must if you need to ensure that something happens regardless (e.g. disposing of a resource etc)
The big difference is that try...catch will swallow the exception, hiding the fact that an error occurred. try..finally will run your cleanup code and then the exception will keep going, to be handled by something that knows what to do with it.

To throw or not to throw an exception in C# [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why catch and rethrow Exception in C#?
I've been scouring the net trying to find the answer to this question - What's the between the two?
try
{
//Do Something
}
catch
{
throw;
}
vs
try
{
//Do Something
}
catch
{
}
or
try
{
//Do Something
}
catch (Exception Ex)
{
//Do something with Exception Ex
}
The first one rethrows the exception up the stack and preserves the stack trace.
The second one swallows (hides) the exception.
The third one probably also swallows the exception but it depends on what (//Do something) does.
catch --> throw will actually just throw your error, so you will have to catch it somewhere else. This can be useful if you want to catch something first and then throw the error to other methods above.
Example:
try
{
// do something
}
catch
{
Console.WriteLine("Something went wrong, and you'll know it");
throw;
}
// won't get here anymore, the exception was thrown.
While try --> catch will just let you ignore the error.
try
{
// do something
}
catch
{
Console.WriteLine("Something went wrong, and you won't know it.");
}
// continuing happily
The first one re-throws the same exception that was caught. the second one swallows the exception as if it never happened. So it depends on what you need.
Please note that there IS a difference between these two:
try
{
//Do Something
}
catch (Exception Ex)
{
//re-throws the same exception that was caught
throw;
}
try
{
//Do Something
}
catch (Exception Ex)
{
//throws a _new_ exception containing Ex
throw Ex;
}
In the first, you are just rethrowing the exception. You don't need try/catch in this case, because you aren't doing anything with the caught exception.
In the second, you are swallowing all exceptions. This is incredibly dangerous. Do not ever do this. It is never correct.
In the last, you haven't given us enough detail to know. You are catching the exception, and you might do something with it. You could rethrow, you could swallow. You haven't told us.
In the first block, an exception is thrown again inside of the handler for the first block. That means that it can be picked up by an outer-try/catch scope block. The second block "eats" the exception in the catch block, and program execution can continue normally after the code in the catch block is executed.
In the first case the exception is rethrown to the caller. This version is pointless because you do nothing with the exception but in practice you may do something and then throw the exception to the caller. It is also useful when filtering exceptions for example
try
{
//do somethign
}
catch(Exception1)
{
throw;
}
catch
{
//do something
}
The second is something you should never do. You are covering an exception and making it harder to catch eventual bug in your application. You either need to handle the exception in a meaningful way or let it break the program (or let the caller handle it)
The third example is simple exception handing. Make sure you don't use it as a form of if/else (flow control)

Thoughts on try-catch blocks

What are your thoughts on code that looks like this:
public void doSomething()
{
try
{
// actual code goes here
}
catch (Exception ex)
{
throw;
}
}
The problem I see is the actual error is not handled, just throwing the exception in a different place. I find it more difficult to debug because i don't get a line number where the actual problem is.
So my question is why would this be good?
---- EDIT ----
From the answers it looks like most people are saying it's pointless to do this with no custom or specific exceptions being caught. That's what i wanted comments on, when no specific exception is being caught. I can see the point of actually doing something with a caught exception, just not the way this code is.
Depending on what quality you are looking at it is not throwing the exception in a different place. "throw" without a target rethrows the exception which is very different from throwing an exception. Primarily a rethrow does not reset the stack trace.
In this particular sample, the catch is pointless because it doesn't do anything. The exception is happily rethrown and it's almost as if the try/catch didn't exist.
I think the construction should be used for handling the exceptions you know you will be throwing inside your code; if other exception is raised, then just rethrow.
Take into account that
throw;
is different than
throw ex;
throw ex will truncate the stack to the new point of throwing, losing valuable info about the exception.
public void doSomething()
{
try
{
// actual code goes here
}
catch (EspecificException ex)
{
HandleException(ex);
}
catch (Exception ex)
{
throw;
}
}
It wouldn't be, ideally the catch block would do some handling, and then rethrow, e.g.,
try
{
//do something
}
catch (Exception ex)
{
DoSomething(ex); //handle the exception
throw;
}
Of course the re-throw will be useful if you want to do some further handling in the upper tiers of the code.
Doing something like that is fairly meaningless, and in general I try not to go down the road of doing meaningless things ;)
For the most part, I believe in catching specific types of exceptions that you know how to handle, even if that only means creating your own exception with more information and using the caught exception as the InnerException.
Sometimes this is appropriate - when you're going to handle the exception higher up in the call stack. However, you'd need to do something in that catch block other than just re-throw for it to make sense, e.g. log the error:
public void doSomething()
{
try
{
// actual code goes here
}
catch (Exception ex)
{
LogException (ex); // Log error...
throw;
}
}
I don't think just rethrowing the error would be useful. Unless you don't really care about the error in the first place.
I think it would be better to actually do something in the catch.
You can check the MSDN Exception Handling Guide.
I've seen instances where generic exceptions are caught like this and then re-packed in a custom Exception Object.
The difference between that and what you're saying is that those custom Exception objects hold MORE information about the actual exception that happened, not less.
Well for starters I'd simply do
catch
{
throw;
}
but basically if you were trapping multiple types of exceptions you may want to handle some locally and others back up the stack.
e.g.
catch(SQLException sex) //haha
{
DoStuff(sex);
}
catch
{
throw;
}
Depends on what you mean by "looks like this", and if there is nothing else in the catch block but a rethrow... if that's the case the try catch is pointless, except, as you say, to obfuscate where the exception occurred. But if you need to do something right there, where the error occurred, but wish to handle the exception furthur up the stack, this might be appropriate. But then, the catch would be for the specific exception you are handl;ing, not for any Exception
Generally having exception handling blocks that don't do anything isn't good at all, for the simple reason that it prevents the .Net Virtual Machine from inlining your methods when performance optimising your code.
For a full article on why see "Release IS NOT Debug: 64bit Optimizations and C# Method Inlining in Release Build Call Stacks" by Scott Hanselman

Categories

Resources