Why is it preferable to throw this Exception
Throw New DivideByZeroException("You can't divide by zero")
over this general one:
Throw New Exception("You can't divide by zero")
What advantage is gained in this particular example? The message already tell it all. Do standard subclasses that inherit from the base Exception class ever have different methods that the base? I haven't seen a case, but I must admit that I tend to throw the base Exception.
The type of the exception allows handlers of the exception to filter it. If all you threw were exceptions of type Exception
how would handlers know what exceptions to catch and which to allow to propagate up the call stack?
For example, if you always throw Exception
:
void Foo(string item) {
try {
if (Bar(item)) {
Console.WriteLine("BAR!");
}
} catch (Exception e) {
Console.WriteLine("Something bad?");
}
}
bool Bar(string item) {
if (item == null) {
throw new Exception("Argument is null!");
}
return Int32.Parse(item) != 0;
}
How does the caller Foo
know if a null exception occurred or if the Int32.Parse()
failed? It has to check the type of the thrown exception (or do some nasty string comparison).
It's even more worrisome if you get a ThreadAbortException
or OutOfMemoryException
which can occur in spots you wouldn't expect an exception. In these cases if your catching code only catches Exception
you may mask these (important) exceptions and cause damage to your program (or system) state.
The example code should read:
void Foo(string item) {
try {
if (Bar(item)) {
Console.WriteLine("BAR!");
}
} catch (ArgumentNullException ae) {
Console.WriteLine("Null strings cannot be passed!");
} catch (FormatException fe) {
Console.WriteLine("Please enter a valid integer!");
}
}
bool Bar(string item) {
if (item == null) {
throw new ArgumentNullException("item");
}
return Int32.Parse(item) != 0;
}
Because you can have multiple catch statements and handle different errors differently.
For example, a DivideByZero exception might prompt the user to correct an entry, while a FileNotFound exception might alert a user that the program can't continue and close the program.
There's a nice in-depth article answering this question here: Link
Rather than filtering based on the text send along the error stream, you can catch multiple types of exceptions. Each one may have a very specific way to perform a recover. The text is just there to provide the user or debugger some feedback, but the program cares about the exception type. For the same reason there is polymorphism for user created classes, there is for exceptions.
It is much easier to include multiple catch statements for different exception types than it is to parse the message text to understand what needs to be done to correctly handle the issue.
Directly from MSDN - Exception Handling:
Consider catching specific exceptions when you understand why it will be thrown in a given context.
You should catch only those exceptions that you can recover from. For example, a
FileNotFoundException
that results from an attempt to open a non-existent file can be handled by an application because it can communicate the problem to the user and allow the user to specify a different file name or create the file. A request to open a file that generates anExecutionEngineException
should not be handled because the underlying cause of the exception cannot be known with any degree of certainty, and the application cannot ensure that it is safe to continue executing.
Do not overuse catch
, as throwing another exception from within a catch block will reset the stack trace and cause the lost of important debugging information, as once again MSDN suggests:
Do not overuse catch. Exceptions should often be allowed to propagate up the call stack.
Catching exceptions that you cannot legitimately handle hides critical debugging information.
In the end, catching an exception should be for handling specific exceptions that you expect to occur under certain common scenario where you would like to log or to have some specific behaviour upon exception catch, otherwise simply throw
it away, as Eric Lippert
himself recommends on his blog (see Too much reuse
article).
try {
...
} catch (Exception ex) {
throw; // This does not reset the stack trace.
}
Instead of:
try {
...
} catch (Exception ex) {
throw ex; // This does reset the stack trace.
}
Finally, an Exception
does not obligatory need to offer some specificities as supplemental properties or methods or whatsoever, it is the name of it that speaks out for itself, allowing you to filter your catch upon a specific type of exception.
EDIT #1
Another interesting link about error handling on Eric Lippert's blog: Vexing exceptions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With