Rethrowing your exceptions wrong in .NET could erase your stacktrace
Niels Swimberghe - - .NET
Follow me on Twitter, buy me a coffee
You may be erasing your stacktrace if you are catching and rethrowing exceptions the wrong way. This could make debugging a nightmare because you don't know where the exception was originally thrown.
You are erasing parts of the stacktrace if you are catching and rethrowing exceptions like this:
try { DoWork(); } catch (Exception ex) { throw ex; }
If you catch the rethrown exception and print out the stacktrace, you will notice that there's no mention of the DoWork
method where the exception was originally thrown.
System.Exception: Exception of type 'System.Exception' was thrown.
at CatchRethrow.Program.IncorrectCatchAndReThrow() in /home/azureuser/CatchRethrow/Program.cs:line 50
at CatchRethrow.Program.Main(String[] args) in /home/azureuser/CatchRethrow/Program.cs:line 22
That's because it was overwritten when the exception was rethrown.
The correct syntax is to use throw;
instead of throw ex;
:
try { DoWork(); } catch (Exception ex) { throw; }
If you catch the rethrown exception now and print out the stacktrace, the DoWork
method is printed as part of the stacktrace:
System.Exception: Exception of type 'System.Exception' was thrown.
at CatchRethrow.Program.DoWork() in /home/azureuser/CatchRethrow/Program.cs:line 56
at CatchRethrow.Program.CorrectCatchAndThrow() in /home/azureuser/CatchRethrow/Program.cs:line 34
at CatchRethrow.Program.Main(String[] args) in /home/azureuser/CatchRethrow/Program.cs:line 12
Luckily, there's a code analysis rule "CA2200: Rethrow to preserve stack details" that will warn you about this.
Here's the full sample of the code used to demonstrate the issue above:
using System; class Program { static void Main(string[] args) { // correct catch/throw try { CorrectCatchAndThrow(); } catch (Exception ex) { Console.WriteLine(ex); /* System.Exception: Exception of type 'System.Exception' was thrown. at CatchRethrow.Program.DoWork() in /home/azureuser/CatchRethrow/Program.cs:line 56 at CatchRethrow.Program.CorrectCatchAndThrow() in /home/azureuser/CatchRethrow/Program.cs:line 34 at CatchRethrow.Program.Main(String[] args) in /home/azureuser/CatchRethrow/Program.cs:line 12 */ } // incorrect catch/throw try { IncorrectCatchAndReThrow(); } catch (Exception ex) { Console.WriteLine(ex); /* System.Exception: Exception of type 'System.Exception' was thrown. at CatchRethrow.Program.IncorrectCatchAndReThrow() in /home/azureuser/CatchRethrow/Program.cs:line 50 at CatchRethrow.Program.Main(String[] args) in /home/azureuser/CatchRethrow/Program.cs:line 22 */ } } static void CorrectCatchAndThrow() { try { DoWork(); } catch (Exception ex) { throw; } } static void IncorrectCatchAndReThrow() { try { DoWork(); } catch (Exception ex) { throw ex; } } static void DoWork() { throw new Exception(); } }