How using try catch for exception handling is best practice
.net, c#, exception, try-catch
Solution
My exception-handling strategy is:
To catch all unhandled exceptions by hooking to the `Application.ThreadException event`, then decide:
- For a UI application: to pop it to the user with an apology message (WinForms)
- For a Service or a Console application: log it to a file (service or console)
Then I always enclose every piece of code that is run externally in `try/catch` :
- All events fired by the WinForms infrastructure (Load, Click, SelectedChanged...)
- All events fired by third party components
Then I enclose in 'try/catch'
- All the operations that I know might not work all the time (IO operations, calculations with a potential zero division...). In such a case, I throw a new `ApplicationException("custom message", innerException)` to keep track of what really happened
Additionally, I try my best to sort exceptions correctly. There are exceptions which:
need to be shown to the user immediately
require some extra processing to put things together when they happen to avoid cascading problems (ie: put .EndUpdate in the `finally` section during a `TreeView` fill)
the user does not care, but it is important to know what happened. So I always log them:
In the event log
or in a .log file on the disk
It is a good practice to design some static methods to handle exceptions in the application top level error handlers.
I also force myself to try to:
- Remember ALL exceptions are bubbled up to the top level. It is not necessary to put exception handlers everywhere.
- Reusable or deep called functions does not need to display or log exceptions : they are either bubbled up automatically or rethrown with some custom messages in my exception handlers.
So finally:
Bad:
// DON'T DO THIS; ITS BAD
try
{
...
}
catch
{
// only air...
}
Useless:
// DON'T DO THIS; IT'S USELESS
try
{
...
}
catch(Exception ex)
{
throw ex;
}
Having a try finally without a catch is perfectly valid:
try
{
listView1.BeginUpdate();
// If an exception occurs in the following code, then the finally will be executed
// and the exception will be thrown
...
}
finally
{
// I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURRED OR NOT
listView1.EndUpdate();
}
What I do at the top level:
// i.e When the user clicks on a button
try
{
...
}
catch(Exception ex)
{
ex.Log(); // Log exception
-- OR --
ex.Log().Display(); // Log exception, then show it to the user with apologies...
}
What I do in some called functions:
// Calculation module
try
{
...
}
catch(Exception ex)
{
// Add useful information to the exception
throw new ApplicationException("Something wrong happened in the calculation module:", ex);
}
// IO module
try
{
...
}
catch(Exception ex)
{
throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}
There is a lot to do with exception handling (Custom Exceptions) but those rules that I try to keep in mind are enough for the simple applications I do.
Here is an example of extensions methods to handle caught exceptions a comfortable way. They are implemented in a way they can be chained together, and it is very easy to add your own caught exception processing.
// Usage:
try
{
// boom
}
catch(Exception ex)
{
// Only log exception
ex.Log();
-- OR --
// Only display exception
ex.Display();
-- OR --
// Log, then display exception
ex.Log().Display();
-- OR --
// Add some user-friendly message to an exception
new ApplicationException("Unable to calculate !", ex).Log().Display();
}
// Extension methods
internal static Exception Log(this Exception ex)
{
File.AppendAllText("CaughtExceptions" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", DateTime.Now.ToString("HH:mm:ss") + ": " + ex.Message + "\n" + ex.ToString() + "\n");
return ex;
}
internal static Exception Display(this Exception ex, string msg = null, MessageBoxImage img = MessageBoxImage.Error)
{
MessageBox.Show(msg ?? ex.Message, "", MessageBoxButton.OK, img);
return ex;
}
Problem
while maintaining my colleague's code from even someone who claims to be a senior developer, I often see the following code: ``` try { //do something } catch { //Do nothing } ``` or sometimes they write logging information to log files like following `try catch` block ``` try { //do some work } catch(Exception exception) { WriteException2LogFile(exception); } ``` I am just wondering if what they have done is the best practice? It makes me confused because in my thinking users should know what happens with the system.