I do not really use any try/catches in my code ever but I'm trying to break that habit and now get in to using exceptions.
I figure the most important place to have it in my application would be reading a file and I'm trying to implement that now but I'm unsure of the "best-practices" for doing so. Currently I'm doing something like this:
private void Parse(XDocument xReader)
{
IEnumerable<XElement> person = xReader.Descendants("Person").Elements();
foreach (XElement e in person)
personDic[e.Name.ToString()] = e.Value;
if (personDic["Name"] == null || personDic["Job"] == null || personDic["HairColor"] == null)
throw new KeyNotFoundException("Person element not found.");
}
But I am unsure if this is correct. I have this for handling it:
try
{
personsReader.Read(filename, persons);
}
catch (KeyNotFoundException e)
{
MessageBox.Show(e.Message);
return;
}
// Do stuff after reading in the file..
However when showing e.Message it just shows the generic KeyNotFoundException error message and not by custom error message. Also I'm not sure if in general I am going about this whole "exception handling stuff" properly. I do return in the catch because if the file is not read successfully obviously I just want to pretend like the user never tried to open a file and let him try again with another file.
Am I doing this properly? Again I am fairly new to using exceptions and I want to make it sure I got it down right before continuing on and applying this to the rest of my program.
Also, why do people say not to do catch (Exception e)? It seems like in this case I would want to do that because regardless of what error occurs when reading in a file, if there is an error, I want to stop reading the file, display the error message, and return. Wouldn't that always be the case? I can understand not wanting to handle Exception e if you would want to handle something differently based on the exception but in this case wouldn't I want to just handle the base exception class in case anything goes wrong?
You should catch exceptions when you can handle the condition and do something useful. Otherwise you should let it bubble up the call stack and perhaps someone above you can handle it. Some apps have unhandled exception handlers to handle it at the outer most layer but in general, unless you know you have some useful way to handle it, let it go.
In your case, you're handling not being able to read a resource and informing the user. You're handling it. Concerning the generic exception, one thing you can do is catch and re-throw a better exception. If you do that, make sure you incude the root cause exception as the inner exception. You can also trace or log the details if appropriate.
throw new MyGoodExceptionType ("Could not read file", e); // e is caught inner root cause.
Now the UI shows a good error and perhaps the inner root cause is in a log etc...
Some typical mistakes:
Handling exceptions deep in the stack in a generic library method: Remember that a common library function may get called in many different code paths. You likely don't have the context whether it should be handled and whether it's appropriate to handle it. the caller higher in the stack likely has context and knows whether it's safe to handle. Typically that means higher layers of code decide to handle. In lower layers, typically you let them flow.
Swallowing Exception: Some code catches exceptions (especially lower in the stack) and then the root condition just evaporates making it maddening to debug. Once agan, if you can handle it, do so. If not, let it go.
Exceptions should be exceptional: Don't use excpetions for flow control. For example, if you're reading a resource, don't try and read and then catch the exception and make a decision point. Instead, call ifexists, check bool and make decisions in your code. this especially helps when you set the debugger to break on exceptions. You should be able to run clean and if the debugger breaks, it should be a real issue. Having the debugger break constantly when debugging is problematic. I personally like throwing exceptions very rarely and always try to avoid for flow control.
Hope that helps.
Ok, first...
... This iss not KeynotFoundException, it should be ArgumentException.... the Argument provided is not valid.
The documentation clearly states:
The exception that is thrown when the key specified for accessing an element in a collection does
not match any key in the collection.
Compare that with:
The exception that is thrown when one of the arguments provided to a method is not valid
Now:
Also, why do people say not to do catch (Exception e)?
Becasue this swallows the exception and makes it impossible to have central error handling / logging in place. ONLY handle exception you expect, UNLESS it is a catch / close something or log it / rethrow (i.e. throw;). Then have a central appdomain handler that gets every uncaptured exceptin and logs it ;) It can not handle anything - because exceptions at that level are unexpected,. It should basically write the excption to a file and be done, possibly with a UI (application has t obe restartet).
As far as what you're doing, it looks mostly ok. I can't speak to whether or not you should be throwing exceptions at that particular point, but the throwing and catching is correctly done. As far as the message, it should be working the way it stands. Try displaying e.ToString() to see the call stack. It could be that simply doing person["Name"] is throwing the KeyNotFoundException first.
As to the question of catching Exception, it's not always bad. Sometimes you cannot predict all possible exceptions, and it's sometimes a good thing to handle any possible failure. However, it gives you no way to handle particular exceptions differently.
As an example, if you get KeyNotFoundException, you might mention something about how the file is incorrectly formatted, and maybe display the file to the user on the screen. If you get FileNotfoundException, you could show them the path and open up an OpenFileDialog to have them select a new file. Exceptions due to security permissions you could display instructions to have them elevate your permissions. Some exceptions may even be recoverable (perhaps one element is badly formatted, but the rest are ok; should it fail the whole thing?)
But, it's ok to catch everything if that's how you want to design it. The most solid program out there would catch every possible exception and handle it in very specific ways, instead of presenting the raw exception to the user. It makes for a better user experience, and gives you ways to work around the problems that can happen.
Most of the time you may not care about the type of exception you get so catching the generic Exception is fine, however there are specific situations in which you would actually want to catch the relevant exception (not just the generic Exception).
One particular example is if you have a thread and you want to interrupt it from a blocking call, in that case you have to distinguish between the InterruptException and the Exception.
Consider this example: you have a thread which runs the Read every minute for 5 minutes (it's not a very realistic example, but it should give you an idea of why you want to handle different exceptions). You have to stop the thread after 5 minutes because your application is going to shut down and you don't want to wait another minute for the running flag to be read... after all, you don't want your user to be waiting for an entire minute just to shut down the application. In order to stop the thread right away, you set the flag to false and you call Interrupt on your thread. In this case you specifically have to catch the ThreadInterrupted exception, because it tells you that you should exit the loop. If you catch another exception, then you've failed to perform the task, but you don't want to give up on the job all together and you would like to try and read again the next minute. This depicts how your requirements dictate the type of exceptions you need to handle. Here is the example in code:
bool running = true;
Thread t = new Thread(()=>
{
while(running)
{
try
{
// Block for 1 minute
Thread.Sleep(60*1000);
// Perform one read per minute
personsReader.Read(filename, persons);
}
catch (KeyNotFoundException e)
{
// Perform a specific exception handling when the key is not found
// but do not exit the thread since this is not a fatal exception
MessageBox.Show(e.Message);
}
catch(InterruptException)
{
// Eat the interrupt exception and exit the thread, because the user
// has signalled that the thread should be interrupted.
return;
}
catch(Exception e)
{
// Perform a genetic exception handling when another exception occurs
// but do not exit the thread since this is not a fatal error.
MessageBox.Show("A generic message exception: " + e.Message);
}
}
});
t.IsBackground = true;
t.Start();
// Let the thread run for 5 minutes
Thread.Sleep(60*5000);
running = false;
// Interrupt the thread
t.Interrupt();
// Wait for the thread to exit
t.Join();
Now on to your other problem with the exception not showing up: note that you're accessing person[e.Name.ToString()] = e.Value which requires a key lookup and if the key is not in the map, then you may get a KeyNotFoundException. That would be the generic exception that you're catching and your custom exception will never be thrown because person[e.Name.ToString()] may throw before you even get to your code.
foreach (XElement e in person)
person[e.Name.ToString()] = e.Value; // <-- May be throwing the KeyNotFoundException
if (person["Name"] == null || person["Job"] == null || person["HairColor"] == null)
throw new KeyNotFoundException("Person element not found.");
Furthermore, you don't want to throw a KeyNotFoundException when you've actually found the key but you didn't find a corresponding value: if person["Name"] == null evaluates to true, then the key "Name" was actually found in the person dictionary, so throwing the KeyNotFoundException would be misleading to anybody who catches that exception. In the case that your value is null, then it would probably not be advisable to throw an exception anyway... it really isn't an exceptional case. You could return a flag indicating that the key was not found:
public bool PerformRead(/*... parameters ...*/)
{
foreach (XElement e in person)
{
// Avoid getting the KeyNotFoundException
if(!person.ContainsKey(e.Name.ToString()))
{
person.Add(e.Name.ToString(), "some default value");
}
person[e.Name.ToString()] = e.Value;
}
if (person["Name"] == null || person["Job"] == null || person["HairColor"] == null)
{
return false;
}
else
{
return true;
}
}
I'm not quite sure why you're not getting your custom error message. That should be happening (unless it's something else throwing a KeyNotFoundException, not the one that you're explicitly throwing).
Also, generally you should put all the code that relies on the file read being successful inside the try, which is often the rest of the body of your method. You no longer would need a return inside your catch block, and subsequent code that doesn't rely on the file read being successful could still execute after a failure.
Example:
public static void Main()
{
var filename = "whatever";
try
{
personsReader.Read(filename, persons);
var result = personsReader.DoSomethingAfterReading();
result.DoSomethingElse();
}
catch (KeyNotFoundException e)
{
MessageBox.Show(e.Message);
}
finally
{
personsReader.CloseIfYouNeedTo();
}
DoSomeUnrelatedCodeHere();
}
And the reason it's good practice not to catch any old Exception e is because you only want to catch and handle the exceptions you're expecting to get. If you get a different kind of exception that you weren't expecting to get, typically this means that something novel failed in a way you didn't anticipate, and you want this behavior to be noticeable, not just get swept under the rug with all the regular error-handling code.
A lot of production-level systems will have one big try/catch around the entire program that catches any exception and performs logging and cleanup before crashing gracefully. This is complemented by having specific try/catch blocks deeper inside the code that handle expected exceptions in a well-defined manner. For unexpected exceptions, you could always just let the CLR bomb ungracefully and figure out what happened from that.
Here's an example of a novel exception. What if something goes terribly wrong and in this line:
IEnumerable<XElement> person = xReader.Descendants("Person").Elements();
...you get an OutOfMemoryException? Should you really just display a popup to the user and allow your program to try to carry on like normal, even though there's simply no way it will be able to? And what if, because you failed silently on an OutOfMemoryException, you later attempt to dereference a null reference, and get a NullReferenceException that causes your program to crash? You'll have a devil of a time trying to track down the root cause of why that reference was null.
Best way to suss out a bug is to fail fast and fail noisily.
"Exceptions are for Exceptional circumstances" - unknown
Don't use the to essentially pass a message out of a method to the calling method. Always try to gracefully handle things. When something really odd happens then throw an exception. This is something that dev not real familiar with how to use exceptions do a lot.
In your code you are triggering the xxx when you evaluate the condition inside the if statement.
Asking person["Name"] == null || person["Job"] == null || person["HairColor"] == null will fail if any of those keys are not in your dictionary.
You need to do this instead:
if (!person.ContainsKey("Name"] ||
!person.ContainsKey("Job"] ||
!person.ContainsKey("HairColor"))
So, your call to throw the exception is never executed! And that's why you never see your message.
I would keep your habit of not doing exceptions for this kind of coding. Exceptions are expensive and can cause real issues in your code to be hidden.
Don't catch general exceptions and don't create exceptions for non-exceptional circumstances.
Related
Learning to log errors.
This is a basic structure of code all through my project.
I have been advised that the try block has to be placed only in Event Handlers.
But when logging the error, it is required to know, which method caused the error.
So, in such cases, should I also keep try block in AllIsFine() & SaveData().
If yes, then should it log the error or just throw.
What is the best/Standard practice.
DataContext objDataContext = new DataContext();
protected void btn_Click(object sender, EventArgs e)
{
try
{
if(AllIsFine())
{
objDataContext.SaveData();
}
}
catch(Exception ex)
{
//some handling
}
}
private bool AllIsFine()
{
//some code
}
EDIT: Ofcourse, we would try to see that it never raises an exception, but not practical. I am looking at it this way. When deployed, the only access I have is to the logs and need to get as much info as possible.So in such cases, (and with this kind of a structure), where do you advise to keep the try catch
I have been advised that the try block has to be placed only in Event
Handlers
This is not true.
There are different type of exceptions, some you need to handle, some you should throw, some you should catch, some you should not. Read this please.
Summary:
You should catch exceptions that you can do something with them
If you want to just log exceptions catch, log, and then use throw not throw ex (it resets the call stack)
Prevent exception from happening if you can, check for conditions that prevent exceptions(IndexOutOfRangeException, NullPointerException, ArgumentNullException) do that instead of executing the action and catch the exception
Don’t catch fatal exceptions; nothing you can do about them anyway, and trying to generally makes it worse.
Fix your code so that it never triggers a boneheaded exception – an "index out of range" exception should never happen in production code.
Avoid vexing exceptions whenever possible by calling the “Try” versions of those vexing methods that throw in non-exceptional
circumstances. If you cannot avoid calling a vexing method, catch its
vexing exceptions.
Always handle exceptions that indicate unexpected exogenous conditions; generally it is not worthwhile or practical to anticipate
every possible failure. Just try the operation and be prepared to
handle the exception.
But when logging the error, it is required to know, which method
caused the error.
You should use the call stack for that.
Try as much as possible to Prevent the Exceptions, and not catching them, if you would Catch an error, try to catch a specific Error, what I mean by that, not try to Catch Exception but something like specific like InvalidCastException.
After catching an Error you should log the exception, but not throwing an exception to log it.
The try-catch statement consists of a try block followed by one or more catch clauses, which specify handlers for different exceptions.
object o2 = null;
try
{
int i2 = (int)o2; // Error
}
It is possible to use more than one specific catch clause in the same try-catch statement. A throw statement can be used in a catch block to re-throw the exception that is caught by the catch statement. You can catch one exception and throw a different exception. When you do this, specify the exception that you caught as the inner exception
catch (FileNotFoundException ex)
{
// FileNotFoundExceptions are handled here.
}
catch (InvalidCastException ex)
{
// Perform some action here, and then throw a new exception.
throw new YourCustomException("Put your error message here.", ex);
}
throw ex; is basically like throwing an exception from that point, so the stack trace would only go to where you are issuing the throw ex; statement
I thought about your question for a while and even if it is already answered, I wanted to share my thoughts.
general
When talking about exception handling, you have to keep in mind what an exception is:
An exception occurs when code cannot run as expected, causing an inconsistent behaviour/state of your application.
This thought leads us to an important rule: Do not catch exceptions that you can’t handle! The Exception system provides security. Think about an accounting software that connects to a database and the connection throws an exception. If you only log the exception and don’t provide any notification about this to the user, he will start to work with the software and when he tries to save, the data will be lost!
You see, it is important where to handle exceptions:
Some of them will be handled by the user (usually in the UI-Layer e.g. View in MVVM/MVC) like the Database exception from the example – only the user can decide if the database is required, the connection string has changed or if a retry will fix the issue.
Others can be handled where they occur; for example code that interacts with some sort of hardware often implements methods with some sort of retry or circuit-breaker logic.
architecture
The where decision is also influenced by the architecture:
Let’s come back to the Database exception scenario: You cannot handle specific exceptions like a MySQL specific Exception (MySqlException) in the UI-Layer because that causes a boundary from you View layer to the specific Model layer implementation and the layering architecture will be broken. However, this is not the topic since your question is about logging exceptions, but you should keep that in mind and probably think about it like this: Catch exceptions of concrete libraries or those that belong to a specific layer/dependency where they occur and log them there and throw new, more generic (probably self-created) exceptions. Those exceptions can be handled in the View-layer and presented to the user.
implementation
The question of where is also important. Since logging is seen as a cross cutting concern. You could think about an AOP framework or, as I have suggested in a comment, by using a decorator pattern. You can compose the logging decorators by basic inversion of control usage and your code will be much cleaner by wrapping everything in try-catch blocks.
If you are using (or planning to use) a DI-container in your application, you could also make use of interception, which would allow you to dynamically wrap you method calls by specified behaviour (like try-catch).
summary
handle your exceptions where you can handle them and log them where you get the most relevant data (e.g. context) from to reproduce the error. But keep in mind that an exception is a security mechanism – it will stop your application when it is no longer in a secure state – when you don’t forward your exceptions (by using throw) and just log them, this could cause not the best user experience.
If you want any code examples, simply ask for them ;)
I want to get all the ip addresses of my computer. If something goes wrong (exception), I simply want empty string returned. Here is the function I use. GetHostEntry will throw several exceptions, and GetHostName also throws exception. How should I handle all these exceptions? Should I catch each of them one by one? That will make code cluttered. Or Should I simply use catch (Exception e) and do nothing inside the catch block? What is the best way to handle it?
private string GetIpAddress()
{
var temp = new StringBuilder();
try {
var hostEntry = Dns.GetHostEntry(Dns.GetHostName());
var ips = from address in hostEntry.AddressList
where (address.AddressFamily == AddressFamily.InterNetwork)
select address;
foreach (IPAddress ip in ips) {
temp.Append(ip).Append(" ");
}
} catch (exception1) {
} catch (exception2) {
} .....
return temp.ToString();
}
You should catch a particular Exception if and only if you can do something useful about it. Otherwise, let the Exception propagate to a level that can do something useful with it.
You should have a global exception handler that elegantly manages otherwise-uncaught exceptions gracefully.
If you really want to just throw away the exception, use an empty catch.
try
{
// Code
}
catch {}
(Note that that's a pair of curly braces, not ()'s)
As a rule of thumb, if you can't handle the exceptions, as evidenced when you have an empty catch block, then you should let them bubble up to the next level.
You should look at each exception that can be thrown and determine exactly why it could be thrown and what you should do about it. For example, if DnsGetHostEntry() can throw an exception, why would it? Should you return a host not found error? Is there a sane default that you should return, that makes sense in your application?
Handle the ones you can do something about, or that you want to handle in a specific way ( think failed to connect driving a message box to prompt whether or not youre connected to the network)
For other "its gone wrong" exceptions, let them propagate up to where we it is meaningful to handle it, or rethrow a meaningful, contextual exception and handle where it is appropriate.
If all youre tryng to do is send a report over a network of some process, to a log file, does it make sense to let that exception kill your process? Not really, so just wrap the top level call to SendNetworkReport.
If its central to your whole process, then let it propagate right up to your main control code, and abort the process in some contextually signifcant way.
Do not mute exceptions, at the very least write a log line. Even if you assume it's going to be a known kind of exception for a known reason.
Don't catch an exception for no apparent reason - let it bubble up
Do put try/catch on every external entry point - event handlers, threads etc. Exception that bubbles up from a button click handler will cause your app to crash, same goes for code on another thread or even on the same thread if forced to run on it (such as Windows.Forms.Control.Invoke(delegate))
Have the least amount of different handlers and only if you're actually treating the exceptions differently
Add a listener to AppDomain.UnhandledException and log these too
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Catching specific vs. generic exceptions in c#
Here's an example method
private static void outputDictionaryContentsByDescending(Dictionary<string, int> list)
{
try
{
//Outputs entire list in descending order
foreach (KeyValuePair<string, int> pair in list.OrderByDescending(key => key.Value))
{
Console.WriteLine("{0}, {1}", pair.Key, pair.Value);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error detected", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
I would like to know what exception clause to use apart from just Exception and if there is an advantage in using more specific catch clauses.
Edit: O.k thanks everyone
Catching individual types of Exceptions in your statement will allow you to handle each in a different way.
A blanket rule for Exception may be useful for logging and rethrowing Exceptions, but isn't the best for actually handling Exceptions that you may be able to recover from.
try
{
// open a file specified by the user
}
catch(FileNotFoundException ex)
{
// notify user and re-prompt for file
}
catch(UnauthorizedAccessException ex)
{
// inform user they don't have access, either re-prompt or close dialog
}
catch(Exception ex)
{
Logger.LogException(ex);
throw;
}
You should only really catch exceptions that you are expecting that code may throw. That way, if it throws something you didn't expect, it may either be something critical; something that should bubble up the call stack and possibly crash the application; or something you have not thought of.
For example, you may wish to handle IOExceptions thrown by I/O code so that you can relay the problem back to the user. However, the same operations may throw something more critical such as an AccessViolationException. In this case, you might want the program to terminate, or handle the problem in a different way.
Generic exception handling should only really be used in cases where you do not care what error occurred, and subsequently don't want it affecting the rest of your process.
The only potential cause for an exception that I see in your example is if list is null. OrderByDescending() should return an empty IEnumerable<> rather than a null reference.
If I read that correctly, it might make more sense to catch NullReferenceException:
try
{
...
} catch (NullReferenceException exception)
{
MessageBox.Show(...);
}
However, this really depends on the needs of your application. If your intention is just to alert the user or to log all exceptions, catching the Exception class is fine. If you need special handling for different types of exceptions - such as sending an email alert instead of just logging the message - then it makes sense to use specific exception types:
try
{
}
catch(NullReferenceException e)
{
//...
}
catch(StackOverflowException e)
{
//...
}
catch(Exception e)
{
/// generic exception handler
}
Which exception to use really depends on the code in the try block. In general you want to catch exceptions that you can do something with and let exceptions you have no power over move to high levels of your code where you can perform some action that makes since. One of the most common mistakes I see people make is attempting to catch errors that they have no ability to handle.
for example
Void ChoseFile()
{
try
{
string FileName = GetInputFile()
}
catch( InvalidFileSelectedException ex)
{
//In this case we have some application specific exception
//There may be a business logic failure we have some ability
//to infomr the user or do an action that makes sense
}
catch(FileNotFoundException exfilenot found)
{
//In this case we can do somthing different the the above
}
catch(Exception )
{
//Normal I would not use this case we have an error we don't know what to do
//with. We may not have a usefull action. At best we can log this exception
// and rethrow it to a higher level of the application that can inform the user
// fail the attempted action. Catching here would only suppress the failure.
}
}
You should always catch exceptions with an as specific class as possible.
If you know what to do if a file is locked, but you regard all other errors as unexpected and impossible to handle, you should catch System.IO.IOException and deal with the error. You should only catch Exception (or just catch {) for gracefully exiting.
Since you are dealing with a Dictionary.. then you want to look at these 2 exceptions
The key of keyValuePair is a null reference (Nothing in Visual Basic).
ArgumentException An element with the same key already exists in the Dictionary(TKey, TValue).
KekValuePair Exception
This is taken from the MSDN site
Use the exception type that you might expect but still not be able to prevent and that you can adequately handle. Let anything else bubble up to somewhere that might expect it or can handle it.
In your case here, I might expect that I would run into a NullReferenceException if the dictionary is null. But I would not catch it. This is something I can validate against instead
if (dictionary != null)
So there is no reason to allow an exception to even happen. Never use exceptions for control flow, and validate against known causes.
Some classes/methods will throw different exceptions, depending on the error. For example, you might be using the File class to write data to a file. You could write multiple Catch statements for the exception types you could recover from, and a generic Exception catch to log and bubble up anything that can't be recovered from.
By using Exception you catch all exceptions. Of you use IOException or StackOverflowException you'll only catch errors of that type.
a StackOverflowException catched by a Exception still hold the same message, stack trace etc.
Exception handling philosophy
I am sure you can find many other philosophies
Code defensively. Catching exceptions is more expensive than preventing the error in the first place.
Don't catch an exception and bury it by not handling it. You can spend many hours trying to find an error that has been suppressed.
Do log errors that you catch.
This helps in analyzing the problem. You can check to see if more than one user is having the same problem
I prefer a database for logging, but a flat file, or the event log are also suitable.
The database solution is easiest to analyze but may introduce additional errors.
If the error is due to bad data entered by the user, inform the user of the problem and allow them to retry.
Always allow an escape route if they cannot fix the problem.
Catch the error as close to the source as possible
This could be a database procedure, a method in a data access layer (DAL) or some other location.
Handling the exception is different than catching it. You may need to rethrow the exception so that it can be handled higher up the stack or in the UI.
Rethrowing the exception can be done in at least two ways.
throw by itself does not alter the stack.
throw ex does alter or add to the stack with no benefit.
Sometimes it is best not to catch an exception, but rather let it bubble up.
If you are writing services (web or windows) that do not have a user interface (UI) then you should always log the error.
Again, this is so that someone can analyze the log or database file to determine what is happening.
You always want someone to know that an error has occurred.
Having a lot of catch statements for a try block can make your code more difficult to maintain, especially if the logic in your catch blocks is complex.
Instead, code defensively.
Remember that you can have try catch blocks within catch blocks.
Also, don't forget to use the finally block where appropriate.
For example, closing database connections, or file handles, etc.
HTH
Harv
Disclaimer, I'm from a Java background. I don't do much C#. There's a great deal of transfer between the two worlds, but of course there are differences and one is in the way Exceptions tend to be thought about.
I recently answered a C# question suggesting that under some circstances it's reasonable to do this:
try {
some work
} catch (Exeption e) {
commonExceptionHandler();
}
(The reasons why are immaterial). I got a response that I don't quite understand:
until .NET 4.0, it's very bad to catch
Exception. It means you catch various
low-level fatal errors and so disguise
bugs. It also means that in the event
of some kind of corruption that
triggers such an exception, any open
finally blocks on the stack will be
executed, so even if the
callExceptionReporter fuunction tries
to log and quit, it may not even get
to that point (the finally blocks may
throw again, or cause more corruption,
or delete something important from the
disk or database).
May I'm more confused than I realise, but I don't agree with some of that. Please would other folks comment.
I understand that there are many low level Exceptions we don't want to swallow. My commonExceptionHandler() function could reasonably rethrow those. This seems consistent with this answer to a related question. Which does say "Depending on your context it can be acceptable to use catch(...), providing the exception is re-thrown." So I conclude using catch (Exception ) is not always evil, silently swallowing certain exceptions is.
The phrase "Until .NET 4 it is very bad to Catch Exception" What changes in .NET 4? IS this a reference to AggregateException, which may give us some new things to do with exceptions we catch, but I don't think changes the fundamental "don't swallow" rule.
The next phrase really bothers be. Can this be right?
It also means that in the event
of some kind of corruption that
triggers such an exception, any open
finally blocks on the stack will be
executed (the finally blocks may
throw again, or cause more corruption,
or delete something important from the
disk or database)
My understanding is that if some low level code had
lowLevelMethod() {
try {
lowestLevelMethod();
} finally {
some really important stuff
}
}
and in my code I call lowLevel();
try {
lowLevel()
} catch (Exception e) {
exception handling and maybe rethrowing
}
Whether or not I catch Exception this has no effect whatever on the excution of the finally block. By the time we leave lowLevelMethod() the finally has already run. If the finally is going to do any of the bad things, such as corrupt my disk, then it will do so. My catching the Exception made no difference. If It reaches my Exception block I need to do the right thing, but I can't be the cause of dmis-executing finallys
For the question #2:
The author meant "Corrupted State Exceptions". They will be introduced in .NET 4.0 (CLR team announced this at PDC 2008 in this talk).
Corrupted state exceptions cannot be caught by normal catch block. Examples: Access violation, Invalid Memory.
But you might want to catch these exceptions:
In main() – write to log, exit, turn off addin
Very rare cases when you know that code throws exception like this (e.g. some cases with interop with native code)
To do this you should put attribute [HandleProcessCorruptedStateException] at the method where you want to catch CorruptedStateException.
To read more about these exceptions please see this MSDN article.
As a general rule you shouldn't catch exceptions unless:
You have a specific exception that you can handle and do something about. However in this case you should always check whether you shouldn't be trying to account for and avoid the exception in the first place.
You are at the top level of an application (for instance the UI) and do not want the default behaviour to be presented to the user. For instance you might want an error dialog with a "please send us your logs" style message.
You re-throw the exception after dealing with it somehow, for instance if you roll back a DB transaction.
Your finally blocks always execute. Your code sample is correct - the low level method should just have try and finally. For instance an unmanaged call might know that it needs to dispose of the unmanaged resource, but this wouldn't be exposed to .Net methods calling it. That call should get rid of the unmanaged resource in its finally block, and calling managed methods can handle exceptions or just pass them on up.
If there's something in an exception that you need to handle you should re-throw the exception, for instance:
try {
conn.BeginTransaction();
//do stuff
conn.CommitTransaction();
}
catch (Exception) {
conn.RollbackTransaction(); //required action on any exception
throw; //re-throw, don't wrap a new ex to keep the stack trace
}
finally {
conn.Dispose(); //always dispose of the resource
}
My motto is handle what you can (or need to) and let any other exceptions bubble up and catch them in an UnhandledException event.
You are correct tho, a finally block is always called (even in the event of an exception being raised in the try section) before you exit the method. So whether you want to the catch the exception on the out method or not is entirely up to you.....this should not affect the finally block being called.
Just to your third question:
If you have
nastyLowLevel() {
doSomethingWhichMayCorruptSomethingAndThrowsException();
}
MyEvilCatcher() {
try {
nastyLowLevel();
} catch (Exception e) {
MyExceptionHandler(e);
}
}
WiseCatcher() {
try {
MyEvilCatcher();
} catch (LowLevelException e) {
DoSomethingWiseSoFinnalyDontRuinAnything();
} finally {
DoSomethingWhichAssumesLowLevelWentOk();
}
}
I think the response you asked about just meant that some low level methods could use exceptions to inform some outer method that special care has to be taken. If you forget about this exceptions in your catch-all-handler and don't rethrow them, something might go wrong.
Generally, I prefer thinking carefully about which exceptions can possibly be thrown and catch them explicitely. I only use "generic handler" at the very outer level in production environments in order to log unexpected exception and present them to the customer in an well-formatted manner (including a hint to send us the log file.)
I think the quoted response is wrong (or maybe meant 2.0 instead of 4.0)? It sounds kinda bogus to me.
I am currently doing a code review and the following code made me jump. I see multiple issues with this code. Do you agree with me? If so, how do I explain to my colleague that this is wrong (stubborn type...)?
Catch a generic exception (Exception ex)
The use of "if (ex is something)" instead of having another catch block
We eat SoapException, HttpException and WebException. But if the Web Service failed, there not much to do.
Code:
try
{
// Call to a WebService
}
catch (Exception ex)
{
if (ex is SoapException || ex is HttpException || ex is WebException)
{
// Log Error and eat it.
}
else
{
throw;
}
}
The mantra is:
You should only catch exceptions if
you can properly handle them
Thus:
You should not catch general
exceptions.
In your case, yes, you should just catch those exceptions and do something helpful (probably not just eat them--you could throw after you log them).
Your coder is using throw (not throw ex) which is good.
This is how you can catch multiple, specific exceptions:
try
{
// Call to a WebService
}
catch (SoapException ex)
{
// Log Error and eat it
}
catch (HttpException ex)
{
// Log Error and eat it
}
catch (WebException ex)
{
// Log Error and eat it
}
This is pretty much equivalent to what your code does. Your dev probably did it that way to avoid duplicating the "log error and eat it" blocks.
I am currently doing a code review and the following code made me jump. I see multiple issues with this code. Do you agree with me?
Not totally, see below.
Catch a generic exception (Exception ex)
In general, catching a generic exception is actually ok as long as you rethrow it (with throw;) when you come to the conclusion that you can't handle it. The code does that, so no immediate problem here.
The use of "if (ex is something)" instead of having another catch block
The net effect of the catch block is that only SoapException, HttpException, etc. are actually handled and all other exceptions are propagated up the call stack. I guess functionality-wise this is what the code is supposed to do, so there's no problem here either.
However, from a aesthetics & readability POV I would prefer multiple catch blocks to the "if (ex is SoapException || ..)". Once you refactor the common handling code into a method, the multiple catch blocks are only slightly more typing and are easier to read for most developers. Also, the final throw is easily overlooked.
We eat SoapException, HttpException and WebException. But if the Web Service failed, there not much to do.
Here possibly lurks the biggest problem of the code, but it's hard to give advice without knowing more about the nature of the application. If the web service call is doing something that you depend on later then it's probably wrong to just log & eat the exceptions. Typically, you let the exception propagate to the caller (usually after wrapping it into e.g. a XyzWebServiceDownException), maybe even after retrying the webservice call a few times (to be more robust when there are spurious network issues).
The problem with catching and re-throwing the same exception is that, although .NET does its best to keep the stack trace intact, it always ends up getting modified which can make tracking down where the exception actually came from more difficult (e.g. the exception line number will likely appear to be the line of the re-throw statement rather than the line where the exception was originally raised). There's a whole load more information about the difference between catch/rethrow, filtering, and not catching here.
When there is duplicate logic like this, what you really need is an exception filter so you only catch the exception types you're interested in. VB.NET has this functionality, but unfortunately C# doesn't. A hypothetical syntax might look like:
try
{
// Call to a WebService
}
catch (Exception ex) if (ex is SoapException || ex is HttpException || /* etc. */)
{
// Log Error and eat it
}
As you can't do this though, what I tend to do instead is use a lambda expression for the common code (you could use a delegate in C# 2.0), e.g.
Action<Exception> logAndEat = ex =>
{
// Log Error and eat it
};
try
{
// Call to a WebService
}
catch (SoapException ex)
{
logAndEat(ex);
}
catch (HttpException ex)
{
logAndEat(ex);
}
catch (WebException ex)
{
logAndEat(ex);
}
I would like to add here, because the Exception handling in almost all java / C# code that I have seen is just incorrect. I.e. you end up with very difficult to debug error for ignored Exceptions, or, equally bad, you get an obscure exception which tells you nothing, because blindly following the "catching(Exception) is bad" and things are just worse.
First, understand that an exception is a way to facilitate the returning of error information across code layers. Now, mistake 1: a layer is not just a stack frame, a layer is code which has a well defined responsibility. If you just coded interfaces and impls just because, well you have better things to fix.
If the layers are well designed and have specific responsibilities, then the information of the error has different meaning as it bubbles up. <-this is the key on what to do, there is no universal rule.
So, this means that when an Exception occurs you have 2 options, but you need to understand where in the layer you are:
A) If you are in the middle of a layer, and you are just an internal, normally private, helper function and something goes bad: DONT WORRY, let the caller receive the exception. Its perfectly OK because you have no business context and
1) You are not ignoring the error and
2) The caller is part of your layer and should have known this can happen, but you might not now the context to handle it down below.
or ...
B) You are the top boundary of the layer, the facade to the internals. Then if you get an exception the default shall be to CATCH ALL and stop any specific exceptions from crossing to the upper layer which will make no sense to the caller, or even worse, you might change and the caller will have a dependency to an implementation detail and both will break.
The strength of an application is the decoupling level between the layers. Here you will stop everything as a general rule and rethrow the error with a generic exception translating the information to a more meaningful error for the upper layer.
RULE: All entry points to a layer shall be protected with CATCH ALL and all errors translated or handled. Now this 'handeled' happens only 1% of the time, mostly you just need (or can) return the error in a correct abstraction.
No I am sure this is very difficult to understand. real Example ->
I have a package that runs some simulations. These simulations are in text scripts. there is a package that compiles these scripts and there is a generic utils package that just reads text files and, of course, the base java RTL. The UML dependency is->
Simulator->Compiler->utilsTextLoader->Java File
1) If something breaks in the utils loader inside one private and I get a FileNotFound, Permissions or what ever, well just let it pass. There is nothing else you can do.
2) At the boundary, in the utilsTextLoader function initially called you will follow the above rule and CATCH_ALL. The compiler does not care on what happen, it just needs to now whether the file was loaded or not. So in the catch, re throw a new exception and translate the FileNotFound or whatever to "Could not read file XXXX".
3) The compiler will now know that the source was not loaded. Thats ALL it needs to know. So if I later I change utilsTestLoader to load from network the compiler will not change. If you let go FileNotFound and later change you will impact compiler for nothing.
4) The cycle repeats: The actual function that called the lower layer for the file will do nothing upon getting the exception. So it lets it go up.
5) As the exception gets to the layer between simulator and compiler the compiler again CATCHES_ALL, hiding any detail and just throws a more specific error: "Could not compile script XXX"
6) Finally repeat the cycle one more time, the simulator function that called the compiler just lets go.
7) The finally boundary is to the user. The user is a LAYER and all applies. The main has a try that catches_ALL and finally just makes a nice dialog box or page and "throws" a translated error to the user.
So the user sees.
Simulator: Fatal error could not start simulator
-Compiler: Could not compile script FOO1
--TextLoader: Could not read file foo1.scp
---trl: FileNotFound
Compare to:
a) Compiler: NullPointer Exception <-common case and a lost night debugging a file name typo
b) Loader: File not found <- Did I mention that loader loads hundreds of scripts ??
or
c) Nothing happens because all was ignored!!!
Of course this assumes that on every rethrow you didn't forget to set the cause exception.
Well my 2cts. This simple rules have saved my life many times...
-Ale
Sometimes that is to only way to handle "catch every exception" scenarios, without actually catching every exception.
I think sometimes, say, lowlevel framework / runtime code needs to make sure that no exception is ever escaping. Unfortunately, there is also no way the framework code can know which exceptions are raised by the code executed by the thread.
In that case a possible catch block could look like this:
try
{
// User code called here
}
catch (Exception ex)
{
if (ExceptionIsFatal(ex))
throw;
Log(ex);
}
There are three important points here, however:
This isn't something for every situation. In code reviews we are very picky about places where this is actually neccessary and thus allowed.
The ExceptionIsFatal() method assures that we don't eat exceptions which should never be swallowed (ExecutionEngineException, OutOfMemoryException, ThreadAbortException, etc.)
What is swallowed is carefully logged (event-log, log4net, YMMV)
Typically, I'm all for the practice of letting uncaught exceptions simply "crash" the application by terminating the CLR. However, especially in server applications, this is sometimes not sensible. If one thread encounters a problem which is deemed non-fatal, there is no reason in ripping the whole process down, killing off all other running requests (WCF, for example, handles some cases this way).
You should usually still catch generic exceptions in a global handler (which is the perfect place to log unexpected Exceptions), but otherwise as said before, you should only catch specific exception types in other places if you plan to do something with them. The catch blocks should look for those exception types explicitly, not as the code you posted does.
I don't think this is such a bad thing in this case, but I also do something similar in my code with exceptions that can be safely ignored being caught and the rest being re-thrown. As noted by Michael's response, having each catch being a separate block could cause some readability issues which are prevented by going this route.
In regards to pointing this out to your colleague, I think you would have a hard time convincing them that this is the wrong way of doing things - even more so if they are stubborn - because of the potential readability issues with doing things the other way. Since this version is still throwing the generic exception's that can't be handled it is in keeping with the spirit of the practice. However, if the code was in line with the following:
try
{
// Do some work
}
catch (Exception ex)
{
if (ex is SoapException)
{
// SoapException specific recovery actions
}
else if (ex is HttpException)
{
// HttpException specific recovery actions
}
else if (ex is WebException)
{
// WebException specific recoery actions
}
else
{
throw;
}
}
Then I think you would have a bit more of a reason to be concerned as there is no point in doing work for a specific exception by checking for it in a general exception block.
the princeple is only to catch the exception you can handle.
such as, if you know how to deal with findnotfound, you catch the filenotfoundexception, otherwiese, do NOT catch it and let it be thrown to the upper layer.