What is the best practice for handling exceptions without having to put try/catch blocks everywhere?
I had the idea of creating a class that is devoted to receiving and handling exceptions, but I am wondering if its a good design idea. Such a class would receive an exception and then decide what to do with it depending on its type or error code, could even parse the stack trace for specific information, etc.
Here is the basic idea behind and implementation:
public class ExceptionHandler
{
public static void Handle(Exception e)
{
if (e.GetBaseException().GetType() == typeof(ArgumentException))
{
Console.WriteLine("You caught an ArgumentException.");
}
else
{
Console.WriteLine("You did not catch an exception.");
throw e; // re-throwing is the default behavior
}
}
}
public static class ExceptionThrower
{
public static void TriggerException(bool isTrigger)
{
if (isTrigger)
throw new ArgumentException("You threw an exception.");
else
Console.WriteLine("You did not throw an exception.");
}
}
class Program
{
static void Main(string[] args)
{
try
{
ExceptionThrower.TriggerException(true);
}
catch(Exception e)
{
ExceptionHandler.Handle(e);
}
Console.ReadLine();
}
}
I thought this would be an interesting endeavor because you would theoretically only need one or very few try / catch blocks around your main() method calls, and let the exception class handle everything else including re-throwing, handling, logging, whatever.
Thoughts?
There is actually a good reason why you don't see similar designs in production code.
First of all, such a design cannot help you reduce the count of try
/catch
pairs in your code (this should be obvious). It could help you reduce the number of catch
statements for a given try
, since you could just catch System.Exception
and forward to the ExceptionHandler
...
But what next?
Every exception needs to be handled differently. How would the ExceptionHandler
know exactly what to do? You could try to solve this in a number of ways, e.g.:
ExceptionHandler
and put the code to handle exceptions in virtual methodsAction<Exception>
instances to the handler and have it invoke the proper oneSolution (1) would be worse than what you had before: now you need to create a whole new class for each try
block and override a bunch of methods to end up with something worse than you had before (it's not immediately clear how the code in a particular class fits in the flow of your program). It would also leave another important question unanswered: you may need context (access to variables in the current scope) to properly handle the exception. How will you provide access to this context?
Solution (2) would actually end up quite similar to writing the catch
blocks that we 've been wanting to avoid (each Action
would be effectively the contents of a catch
block). We end up doing the same thing, only in a more complicated and verbose manner.
There are also other issues:
ExceptionHandler
do if it cannot handle the exception? Throwing it again will cause you to lose the original stack trace, in effect destroying all the good information in there.ExceptionHandler
? You can truse a try
/catch
. Can you trust code you wrote yourself to the same degree?As for the ExceptionThrower
... what benefit could it possibly offer over throw new Exception();
?
Exception handling is a complicated matter already, and it's difficult enough to get it right without adding extra gears to the machine. Especially if they don't buy you anything new. Don't do it.