Understanding the difference between throw ex and throw, why is the original StackTrace preserved in this example:
static void Main(string[] args)
{
try
{
LongFaultyMethod();
}
catch (System.Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
static void LongFaultyMethod()
{
try
{
int x = 20;
SomethingThatThrowsException(x);
}
catch (Exception)
{
throw;
}
}
static void SomethingThatThrowsException(int x)
{
int y = x / (x - x);
}
But not in this one:
static void Main(string[] args)
{
try
{
LongFaultyMethod();
}
catch (System.Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
static void LongFaultyMethod()
{
try
{
int x = 20;
int y = x / (x - 20);
}
catch (Exception)
{
throw;
}
}
The second scenario is producing the same output as throw ex would?
In both cases, one expects to see the line number where y is initialized.
I’m not sure whether this limitation is within the C# language, the CLI, or the Microsoft implementation of these, but your second example is a case where an explicit call to
Exception.InternalPreserveStackTraceis required as documented in the following post. Since this method isinternal, it generally has to be called through reflection. The performance issues involved in this can be almost completely alleviated by creating anAction<Exception>for the call, as shown at the end of this answer.Reference: Rethrowing exceptions and preserving the full call stack trace
Edit: After reexamining ECMA-335 Partition I §12.4.2 (Exception handling) and Partition III §4.24 (rethrow), I now believe that the behavior you are seeing is a semantic error in the CLR (Microsoft’s implementation of the CLI). The only specific reference to the behavior is “A
rethrowdoes not change the stack trace in the object.” In the case described here, the rethrow is in fact altering the stack trace, making thePreserveStackTracehack a workaround for a know CLR flaw.PreserveStackTracehere is an optimization of the one from that blog entry: