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.
Related
I know that there are some exception types that cannot be caught in catch blocks, like StackOverflowException in .NET 2.0. I would like to know which other exceptions are inadvisable to catch, or are associated with bad practices.
The way I would like to use this list of exception types is to check it every time I am using Exception in a catch block:
private static readonly Type[] _exceptionsToNotCatch = new Type[] { typeof(StackOverflowException) };
// This should never throw, but should not swallow exceptions that should never be handled.
public void TryPerformOperation()
{
try
{
this.SomeMethodThatMightThrow();
}
catch (Exception ex)
{
if (_exceptionsToNotCatch.Contains(ex.GetType()))
throw;
}
}
EDIT
I don't think I provided a very good example. That's one of the problems with trying to make an example trivial when trying to communicate one's meaning.
I never throw Exception myself, and I always catch specific exceptions, only catching Exception as follows:
try
{
this.SomeMethodThatMightThrow();
}
catch (SomeException ex)
{
// This is safe to ignore.
}
catch (Exception ex)
{
// Could be some kind of system or framework exception, so don't handle.
throw;
}
My question was meant as more of an academic one. What exceptions are only thrown by the system and should never be caught? I am worried about situations more like this:
try
{
this.SomeMethodThatMightThrow();
}
catch (OutOfMemoryException ex)
{
// I would be crazy to handle this!
// What other exceptions should never be handled?
}
catch (Exception ex)
{
// Could be some kind of system or framework exception, so don't handle.
throw;
}
This question was really inspired by the following:
System.Data.EntityUtil.IsCatchableExceptionType(Exception) in System.Data.Entity, Version=3.5.0.0
I would like to know which other exceptions are inadvisable to catch, or are associated with bad practices.
Here is the list of all exceptions you shouldn't catch:
Any exception you don't know what to do with
Here's the best practice for exception handling:
If you don't know what to do with an exception, don't catch it.
This may sound snarky, but they're both correct, and that's all you need to know.
It's generally not a good idea to do that.
You should catch the most specific exception(s) possible and only carry on execution of your program when it is safe to do so. E.g. if you're opening a file, it's perfectly reasonable to catch exceptions relating to file access / permission errors, but probably not much else. You certainly wouldn't want to catch an OutOfMemoryException and then blindly carry on. They're very different errors!
If you apply a blanket rule of what to catch, there's no guarantee that your program will be able to continue execution safely because you're not responding to specific situations, just applying a one size does not fit all solution.
Using Exception in the catch block would catch all exceptions that are catchable. I would say you should specify only exceptions that needs to be caught and let the ones you don't want to catch spill out. E.g.
try
{
}
catch(SqlException sqlex) //specific to database calls
{
//do something with ex
}
catch(FormatException fex) //specific to invalid conversion to date, int, etc
{
//do something with ex
}
catch(Exception ex)
{
//I didn't know this exception would be thrown
//log it for me or Rethrow it
}
Any other exception not in that list will not be caught
Okay so we've established it ain't a good idea. And we've established that programmers on SO prefer to opine from their high-horses rather than hand you a knife to stab yourself with, so for those with suicidal tendencies, let's start with these:
(Redacted my list and DRYing-up SO to point to Hans' list)
https://stackoverflow.com/a/5508733/17034
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.
Is it recommended to put a try-catch block in every function that opens a DB connection and log the error there, or should I rather catch errors in a higher layer of the application?
public static Category GetCategoryByName(string name)
{
Category result;
try
{
using (IDbConnection conn = ConnectionHelper.CreateDbConnectionByName(_connectionStringName))
{
conn.Open();
using (IDbCommand cmd = conn.CreateCommand())
{
//do stuff
}
}
}
catch(Exception e)
{
// log error here?
}
return result;
}
or rather
try
{
Category myCat = DataTools.GetCategoryByName("myCat");
// other stuff
}
catch(Exception e)
{
// log error here?
}
To sum it up: Should errors be caught as early as possible in the code? Or should I rather catch them where I have more information about the context?
As always, it depends, but in general, only catch an exception if you can do something about it, or you have specific code (e.g. a retry) to happen, or if you wish to take a very general exception and wrap it into an exception that is more specific for your business logic, otherwise, let the exception bubble up and the top most layer can log it/deal with it in a centralised fashion.
Any other way results in a lot of logging code interspersed with all the business logic.
When catching exceptions, always try to use the most accurate exception you can. For example, when using SQL Server, catch the SqlException as it will contain far more information about the exceptin than a generic Exception. You can get actual line numbers and other useful pieces of diagnostic information.
After you have extracted and logged all that is relevent, rethrow the exception or wrap it in less specific exception such as an InvalidDataException or Exception and throw that. You can then catch these more generic exceptions at higher levels.
try
{
// Execute DB call here
}
catch(SqlException exp)
{
// Log what you need from here.
throw new InvalidOperationException("Data could not be read", exp);
}
When you call this method from a higher level, you can just catch the InvalidOperationException. If the higher levels do need more detail, the InnerException will provide the SqlException which can be accessed.
The general approach to exception handling that I follow is to only catch what I can usefully act upon. There no point in catching really general Exception at lower levels of the code since you can really expect everything to go wrong or to be able to recover from every exception e.g. OutOfMemoryException or StackOverflowException.
I Usually only handle exceptions in the UI, everything below that I always throw it back to the top level. This way the stack trace has been maintained all the way though. You could always log and throw it.
I have used this before also:
try
{
DB Command
}
catch (Exception ex)
{
Log(ex)
throw; //preserve stacktrace
}
I like the first approach better, but you still have to work out what else to do i the catch block...
rethrow the exception?
throw another (more general) exception?
return null to the caller?
what is a best practice in cases such as this one:
try
{
// do something
}
catch (SpecificException ex)
{
Response.Redirect("~/InformUserAboutAn/InternalException/");
}
the warning i get is that ex is never used.
however all i need here is to inform the user, so i don't have a need for it.
do i just do:
try
{
// do something
}
catch
{
Response.Redirect("~/InformUserAboutAn/InternalException/");
}
somehow i don't like that, seems strange!!? any tips? best practices?
what would be the way to handle this.
thnx
You just don't declare the variable:
try
{
// do something
}
catch (SpecificException)
{
Response.Redirect("~/InformUserAboutAn/InternalException/");
}
This is a moot point when catching System.Exception (in your original example, which is not exactly the same as an empty catch -- an empty catch will also catch COM exceptions, for instance), but this is the correct construct to use.
If you run your code through other analysis engines (Gendarme, for instance), you will also be warned that catching a plain Exception is poor practice because it can mask other exceptions besides what you really wanted to catch. That's bitten me a few times while maintaining legacy code -- we were catching and ignoring an Exception on a file delete (or something like that), but the main logic wasn't working correctly. We should have been only catching an IOException, but we were catching and discarding the NullReferenceException that was causing the failure.
That's not to say you never should catch Exception; just rarely.
If you don't need Exception's variable to get some information from it, don't declare it
try { }
catch ( )
is equal to
try { }
catch (Exception) { }
Use this
try { }
catch (Exception ex) { var m = ex.Message; }
if you need some information to gather.
Use this
try { }
catch (FooException) { }
catch (BarException) { }
if you need to catch only specific types of exceptions, i.e. SomeAnotherException will not be caught.
It would be better if you just let the exception bubble all the way up and use an application wide exception handler or something like ELMAH. Usually you'll want to log the exception or something so there's a record of stuff failing.
Any reason why you wouldn't let unhandled exceptions simply throw and use the Application Level error handling built into ASP.NET? See How to: Handle Application-Level Errors for more details.
I usually declare it and suffer with the warning since it can be very useful to be able to look at the exception details while debugging.
There are two reasons to declare an exception variable in a catch block. To catch only specific exception types or to do something with the exception info. In your case you are doing neither so t serves no purpose.
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