Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the point of passing ExceptionDispatchInfo around instead of just the Exception?

Tags:

I understand the value of ExceptionDispatchInfo.Capture(e).Throw() (preserves the original stack trace), but what's the advantage of using Capture early and passing the ExceptionDispatchInfo around vs. just passing the caught Exception around?

As a concrete example, comparing

static Exception CaptureException(Action action) {   try   {     action();     return null;   }   catch (Exception e)   {     return e;   } }  public void Test1() {   ExceptionDispatchInfo.Capture(CaptureException(        () => throw new IOException("Test")))     .Throw(); } 

with

static ExceptionDispatchInfo CaptureDispatchInfo(Action action) {   try   {     action();     return null;   }   catch (Exception e)   {     return ExceptionDispatchInfo.Capture(e);   } }  public void Test2() {   CaptureDispatchInfo(() => throw new IOException("Test")).Throw(); } 

, both give essentially the same stack traces (It's similar for an async variation of this.). So, I don't really get why the ExceptionDispatchInfo class exists at all, rather than just a combined ExceptionDispatchInfo.Capture(e).Throw() method.

like image 729
FunctorSalad Avatar asked Aug 16 '17 21:08

FunctorSalad


People also ask

Should I rethrow exceptions?

Upon determining that a catch block cannot sufficiently handle an exception, the exception should be rethrown using an empty throw statement. Regardless of whether you're rethrowing the same exception or wrapping an exception, the general guideline is to avoid exception reporting or logging lower in the call stack.

What is the best way to re throw an exception?

If a catch block cannot handle the particular exception it has caught, you can rethrow the exception. The rethrow expression ( throw without assignment_expression) causes the originally thrown object to be rethrown.

What is ExceptionDispatchInfo?

The ExceptionDispatchInfo object stores the stack trace information and Watson information that the exception contains at the point where it is captured. The exception can be thrown at another time and possibly on another thread by calling the ExceptionDispatchInfo. Throw method.

Which of the following keyword can be used to Rethrow an exception in C#?

To rethrow an exception, you can use the <throw> keyword.


1 Answers

You're assuming that exceptions are immutable. This is not the case - an exception's StackTrace changes when it's re-thrown.

The purpose of ExceptionDispatchInfo.Capture is to capture a potentially mutating exception's StackTrace at a point in time:

void Foo() => throw new InvalidOperationException ("foo");  Exception original = null; ExceptionDispatchInfo dispatchInfo = null; try {     try     {         Foo();     }     catch (Exception ex)     {         original = ex;         dispatchInfo = ExceptionDispatchInfo.Capture (ex);         throw ex;     } } catch (Exception ex2) {     // ex2 is the same object as ex. But with a mutated StackTrace.     Console.WriteLine (ex2 == original);  // True }  // So now "original" has lost the StackTrace containing "Foo": Console.WriteLine (original.StackTrace.Contains ("Foo"));  // False  // But dispatchInfo still has it: try {     dispatchInfo.Throw (); } catch (Exception ex) {     Console.WriteLine (ex.StackTrace.Contains ("Foo"));   // True } 
like image 130
Joe Albahari Avatar answered Oct 10 '22 06:10

Joe Albahari