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
At first, I was going to do something like the following:
public void WriteToFile(string filePath, string contents)
{
try
{
File.WriteAllText(filePath, contents)
}
catch(Exception ex)
{
//Log error
}
}
But then I decided to catch all the specific exceptions for the method WriteAllText, like the following:
public void WriteToFile(string filePath, string contents)
{
try
{
File.WriteAllText(filePath, contents);
}
catch (IOException ex)
{
//An I/O error occured when opening the file
}
catch (ArgumentException ex)
{
//The exception that is thrown when one of the arguments provided to a method
that is not valid.
}
catch (UnauthorizedAccessException ex)
{
//Unauthorized access
}
catch (SecurityException ex)
{
//Security exception
}
catch (NotSupportedException ex)
{
//Invoked method not supported
}
}
The above is very verbose and with other methods, it could be more. Is there a better way to do this so I don't have to write so many catch statements. Also, if an exception is caught, is it best to return from it, log it. I always get confused on how to handle it.
I have noticed some confusion. I am going to handle the exceptions, I left out handling the exception to keep this short. I am going to make use of the ex variable. The question is more about doing just catch(Exception ex) or multiple catch statements.
I also bring this up because I always here that it is better to handle specific exceptions rather than a catch-all. If I have misunderstood this, please clarify on what it means.
It depends on how you are handling the exception. For example, if a SecurityException will cause you to present a dialog to the user to provide their credentials, then you should have a separate catch clause. If not, there is no need to explicitly call them all out.
E.g.
try
{
File.WriteAllText(filePath, contents);
}
catch (SecurityException ex)
{
//present dialog
}
catch (Exception ex)
{
//All other exceptions handled the same
}
Typicaly, your try/catch statements will be much further up the call stack from what you are showing in the question. There are two major reasons for this. First is that a low-level method will not know how to deal with an exception that happens within it, because it does not have enough context. If a low-level method (such as one that saves a document) does know enough about its circumstances to handle the exceptions, then that is a sign of a leaky abstraction. Second is that the program flow at higher levels will depend on whether the save operation succeeded or not. For these reasons, all of these types of exceptions are best delt with at the highest levels, such as in the UI layer.
That said, sometimes a long list of exceptions—as you have it—is exactly the way to go. If you need to handle a bunch of different circumstances, then it calls for a bunch of different catch statements, and that's just the way it goes.
Some of those exceptions, however, do not need to be caught. For example, an ArgumentException never needs to be caught. Instead, it is best just to pass the correct arguments every time. The only time an ArgumentException will ever need to be caught is if you are calling into a poory designed library in which you cannot know beforehand whether an argument is good or not. A well-designed library will provide alternatives to this.
So the list of catch statements could be made shorter, just by judiciously examining the circumstances of each type of exception and determining which ones are actually expected to happen.
I agree with SLaks above. If you don't handle it there is no reason in catching specific exceptions. If you can handle certain exceptions but not others you should have a catch all that at least logs vital information about the exception.
The best method very much depends on the nature of your application and the expectations of the user. If you are creating a Word processing application and your operation above was to save the user's document, swallowing the exception and logging without notifying the user would be very bad! In this context, I would catch the specific exceptions so that I could better report to the user what the problem is.
If instead the file you are saving is non-critical, e.g. a period caching of some data that is retained in memory, you might want to simply log and not notify the user. In this context, I would go for a generic catch-all and just log the exception details.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
What are some of the most common mistakes you've seen made when handling exceptions?
It seems like exception handling can be one of the hardest things to learn how to do "right" in .Net. Especially considering the currently #1 ranked answer to Common programming mistakes for .NET developers to avoid? is related to exception handling.
Hopefully by listing some of the most common mistakes we can all learn to handle exceptions better.
What are some of the most common mistakes you've seen made when handling exceptions?
I can think of lots.
First read my article on categorization of exceptions into vexing, boneheaded, fatal and exogenous:
http://ericlippert.com/2008/09/10/vexing-exceptions/
Some common errors:
Failure to handle exogenous exceptions.
Failure to handle vexing exceptions.
Construction of methods that throw vexing exceptions.
Handling exceptions that you actually cannot handle, like fatal exceptions.
Handling exceptions that hide bugs in your code; don't handle a boneheaded exception, fix the bug so that it isn't thrown in the first place
Security error: failure to the unsafe mode
try
{
result = CheckPassword();
if (result == BadPassword) throw BadPasswordException();
}
catch(BadPasswordException ex) { ReportError(ex); return; }
catch(Exception ex) { LogException(ex); }
AccessUserData();
See what happened? We failed to the unsafe mode. If CheckPassword threw NetworkDriverIsAllMessedUpException then we caught it, logged it, and accessed the user's data regardless of whether the password was correct. Fail to the safe mode; when you get any exception, assume the worst.
Security error: production of exceptions which leak sensitive information, directly or indirectly.
This isn't exactly about handling exceptions in your code, it's about producing exceptions which are handled by hostile code.
Funny story. Before .NET 1.0 shipped to customers we found a bug where it was possible to call a method that threw the exception "the assembly which called this method does not have permission to determine the name of file C:\foo.txt". Great. Thanks for letting me know. What is stopping said assembly from catching the exception and interrogating its message to get the file name? Nothing. We fixed that before we shipped.
That's a direct problem. An indirect problem would be a problem I implemented in LoadPicture, in VBScript. It gave a different error message depending upon whether the incorrect argument is a directory, a file that isn't a picture, or a file that doesn't exist. Which means you could use it as a very slow disk browser! By trying a whole bunch of different things you could gradually build up a picture of what files and directories were on someone's hard disk. Exceptions should be designed so that if they are handled by untrustworthy code, that code learns none of the user's private information from whatever they did to cause the exception. (LoadPicture now gives much less helpful error messages.)
Security and resource management error: Handlers which do not clean up resources are resource leaks waiting to happen. Resource leaks can be used as denial-of-service attacks by hostile partial trust code which deliberately creates exceptions-producing situations.
Robustness error: Handlers must assume that program state is messed up unless handling a specific exogenous exception. This is particularly true of finally blocks. When you're handling an unexpected exception, it is entirely possible and even likely that something is deeply messed up in your program. You have no idea if any of your subsystems are working, and if they are, whether calling them will make the situation better or worse. Concentrate on logging the error and saving user data if possible and shut down as cleanly as you can. Assume that nothing works right.
Security error: temporary global state mutations that have security impacts need to be undone before any code that might be hostile can run. Hostile code can run before finally blocks run! See my article on this for details:
http://blogs.msdn.com/ericlippert/archive/2004/09/01/224064.aspx
Re-throwing exceptions like this:
try
{
// some code here
}
catch(Exception ex)
{
// logging, etc
throw ex;
}
This kills the stack trace, making is far less usable. The correct way to rethrow would be like this:
try
{
// some code here
}
catch(Exception ex)
{
// logging, etc
throw;
}
Catching all exceptions when in many cases you should attempt to catch specific exceptions:
try {
// Do something.
} catch (Exception exc) {
// Do something.
}
Rather than:
try {
// Do something.
} catch (IOException exc) {
// Do something.
}
Exceptions should be ordered from most specific to least.
Rethrowing an exception with a meaningless message.
try
{
...
}
catch (Exception ex)
{
throw new Exception("An error ocurred when saving database changes").
}
You won't believe how often I see code like this running in production.
Nobody is talking about seeing empty catch blocks like these....
try{
//do something
}
catch(SQLException sqex){
// do nothing
}
Also never use Exception handling for creating alternate method flows...
try{
//do something
}catch(SQLException sqex){
//do something else
}
Not using using on IDisposable objects:
File myFile = File.Open("some file");
callSomeMethodWhichThrowsException(myFile);
myFile.Close();
myFile does not get closed until myFile's finalizer is called (which may be never) because an exception was thrown before myFile.Close() was called.
The proper way to do this is
using(File myFile = File.Open("some file"))
{
callSomeMethodWhichThrowsException(myFile);
}
This gets translated by the compiler into something like:
File myFile = File.Open("some file");
try
{
callSomeMethodWhichThrowsException(myFile);
}
finally
{
if(myFile != null)
myFile.Dispose(); //Dispose() calls Close()
}
So the file gets closed even in the face of exceptions.
Forget to set the inner exception when rethrowing a catched exception
try
{
...
}
catch (IOException ioException)
{
throw new AppSpecificException("It was not possible to save exportation file.")
// instead of
throw new AppSpecificException("It was not possible to save exportation file.", ioException);
}
When I posted this answer, I forget to mention that we should always consider when to include inner exception or not due to security reasons. As Eric Lippert pointed out on another answer for this topic, some exceptions can provide sensitive information about the implementation details of the server. Thus, if the caller who will be handling the exception is not trusted, it is not a good idea to include the inner exception information.
Empty catch:
//What's the point?
catch()
{}
Rethrowing:
//Exceptions are for *adding* detail up the stack
catch (Exception ex)
{throw ex;}
Assuming an exception that covers many scenarios was something specific. A real life scenario was a web app where the exception handling always assumed all errors were session time outs and logged and reported all errors as session time outs.
Another example:
try
{
Insert(data);
}
catch (SqlException e)
{
//oh this is a duplicate row, lets change to update
Update(data);
}
To log Exception.Message instead of Exception.ToString()
Many times, I see code logging only the exception message while it should log the return of ToString method. ToString provides much more information about the exception than the Message. It includes information like inner exception and stack trace besides the message.
Trying to catch OutOfMemoryException or StackOverflowException - those lead to a shutdown of the runtime, hence to way to catch them from within the same Process (or even from the CLR as a whole?)
OutOfMemoryException: The exception that is thrown when there is not enough memory to continue the execution of a program.
"Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default. Consequently, users are advised to write their code to detect and prevent a stack overflow."
Failing to catch possible exceptions inside a catch handler. This can cause the wrong exception to be propagated upwards.
For example:
try
{
DoImportantWork();
}
catch
{
Cleanup();
throw;
}
What happens if Cleanup() throws an exception? You don't want to see an Exception pointing to the Cleanup() method in this catch handler. You want the original error. You could try to log the cleanup error, but even your logging code needs exception handling to avoid throwing exceptions from it.
try
{
DoImportantWork();
}
catch
{
try
{
Cleanup();
}
catch
{
// We did our best to clean up, and even that failed.
// If you try to log this error, the logging may throw yet another Exception.
}
throw;
}
Wrong
try
{
// Do something stupid
}
catch
{
// ignore the resulting error because I'm lazy, and later spend
// a week trying to figure out why my app is crashing all over
// the place.
}
Better
try
{
/// do something silly.
}
catch (InvalidOperationException ex)
{
/// respond, or log it.
}
catch (Exception e)
{
/// log it.
}
Using exceptions for normal flow control. Exceptions should exceptional. If it's a good / expected operation, use return values, etc.
I maintain a c# compact framework application and have had 2 cases in 2 days where the a caught exception had a unexpected string in the Message. Both times due to a different exception type being thrown. In the following code the socket exception is caught, but the message shown relates to something else.
//method1
try
{
soc.Connect(new IPEndPoint(IPAddress.Parse(_serverAddress), _serverPort));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message)
}
//method2
try
{
m_socServer.Connect(new IPEndPoint(IPAddress.Parse(_serverAddress), _serverPort));
}
catch (SocketException sex)
{
MessageBox.Show(sex.Message)
}
In 'method1' the exception is thrown upon fail to connect, the catch block entered, but the message box shown an exception I know is from outside of this try block. In 'method2' the exception is caught and the message is correct. These two try catch blocks are the only thing changed in the code.
I have yet to reproduce this in a small test program, but the program I maintain has this behaviour.
Where and why does 'method1' not get the unexpected value?
You are probably mistaken - in these 2 cases, some other exception (the one you're receiving) is being thrown instead of a SocketException.
If you're only expecting SocketException to be thrown, you should only provide a handler for that case. Other exceptions, in this situation, are probably truly exceptional - meaning that you aren't going to be able to correctly recover.
In that case, it's usually better to not handle the exception, and let it bubble up. If you feel that this is incorrect, put in the SocketException handler AND a generic exception handler, and make sure to check your stack traces (and potentially InnerException properties) in the exceptions:
try
{
//throw SocketException
}
catch (SocketException sockEx)
{
MessageBox.Show(sockEx.Message)
}
catch (Exception ex)
{
MessageBox.Show(ex.Message)
}
The statement you have above will catch ALL Exceptions, not just a specific type of exception.
If you want to handle specific exception types, you need to have code similar to this:
try
{
// Do some work.
}
catch(SocketException ex)
{
// Handle a known SocketException
}
catch(NullReferenceException ex)
{
// Handle a known NullReferenceException
}
catch(OtherSpecificException ex)
{
// You get the idea
}
catch(Exception ex)
{
// This will be everything else you haven't explicitly caught.
// It will also give you the most generic details about the Exception.
}
When you handle exceptions you can think of who needs to be notified of the error: the user? or the admin/developer?
You can define that a SocketException contains a message that the user needs to be notified of, and every other exception should be saved for developers or administrators to see. For example you can write the full exception to a file, or event you can have a special MessageBox. "Unexpected Error, please notify the administrator: " + ex.ToString().
Make sure you write the whole ex.ToString() because it includes the stacktrace and all InnerException's.
The best practice is to keep the catch(Exception ex) on the outer level of your application so you handle all unexpected exception in one place.
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