c# - Best practices for catching and re-throwing .NET exceptions

ID : 10413

viewed : 27

Tags : c#.netexception-handlingrethrowc#

Top 5 Answer for c# - Best practices for catching and re-throwing .NET exceptions

vote vote


The way to preserve the stack trace is through the use of the throw; This is valid as well

try {   // something that bombs here } catch (Exception ex) {     throw; } 

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.

Mike is also correct, assuming the exception allows you to pass an exception (which is recommended).

Karl Seguin has a great write up on exception handling in his foundations of programming e-book as well, which is a great read.

Edit: Working link to Foundations of Programming pdf. Just search the text for "exception".

vote vote


If you throw a new exception with the initial exception you will preserve the initial stack trace too..

try{ }  catch(Exception ex){      throw new MoreDescriptiveException("here is what was happening", ex); } 
vote vote


Actually, there are some situations which the throw statment will not preserve the StackTrace information. For example, in the code below:

try {   int i = 0;   int j = 12 / i; // Line 47   int k = j + 1; } catch {   // do something   // ...   throw; // Line 54 } 

The StackTrace will indicate that line 54 raised the exception, although it was raised at line 47.

Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.    at Program.WithThrowIncomplete() in Program.cs:line 54    at Program.Main(String[] args) in Program.cs:line 106 

In situations like the one described above, there are two options to preseve the original StackTrace:

Calling the Exception.InternalPreserveStackTrace

As it is a private method, it has to be invoked by using reflection:

private static void PreserveStackTrace(Exception exception) {   MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",     BindingFlags.Instance | BindingFlags.NonPublic);   preserveStackTrace.Invoke(exception, null); } 

I has a disadvantage of relying on a private method to preserve the StackTrace information. It can be changed in future versions of .NET Framework. The code example above and proposed solution below was extracted from Fabrice MARGUERIE weblog.

Calling Exception.SetObjectData

The technique below was suggested by Anton Tykhyy as answer to In C#, how can I rethrow InnerException without losing stack trace question.

static void PreserveStackTrace (Exception e)  {    var ctx = new StreamingContext  (StreamingContextStates.CrossAppDomain) ;    var mgr = new ObjectManager     (null, ctx) ;    var si  = new SerializationInfo (e.GetType (), new FormatterConverter ()) ;     e.GetObjectData    (si, ctx)  ;    mgr.RegisterObject (e, 1, si) ; // prepare for SetObjectData    mgr.DoFixups       ()         ; // ObjectManager calls SetObjectData     // voila, e is unmodified save for _remoteStackTraceString  }  

Although, it has the advantage of relying in public methods only it also depends on the following exception constructor (which some exceptions developed by 3rd parties do not implement):

protected Exception(     SerializationInfo info,     StreamingContext context ) 

In my situation, I had to choose the first approach, because the exceptions raised by a 3rd-party library I was using didn't implement this constructor.

vote vote


When you throw ex, you're essentially throwing a new exception, and will miss out on the original stack trace information. throw is the preferred method.

vote vote


The rule of thumb is to avoid Catching and Throwing the basic Exception object. This forces you to be a little smarter about exceptions; in other words you should have an explicit catch for a SqlException so that your handling code doesn't do something wrong with a NullReferenceException.

In the real world though, catching and logging the base exception is also a good practice, but don't forget to walk the whole thing to get any InnerExceptions it might have.

Top 3 video Explaining c# - Best practices for catching and re-throwing .NET exceptions