using System; namespace CallStackPreservation { class Program { private static void BadWork() { int i = 0; int j = 12 / i; // Line 10 int k = j + 1; } private static void WithThrowEx() { try { BadWork(); } catch (Exception ex) { // do something // ... throw ex; // Line 24 } } private static void WithThrow() { try { BadWork(); } catch { // do something // ... throw; // Line 38 } } private static void WithThrowIncomplete() { try { int i = 0; int j = 12 / i; // Line 47 int k = j + 1; } catch { // do something // ... throw; // Line 54 } } private static void WithThrowExAndStackTracePreservation() { try { BadWork(); } catch (Exception ex) { // do something // ... PreserveStackTrace(ex); throw ex; // Line 69 } } private static void WithThrowAndStackTracePreservation() { try { int i = 0; int j = 12 / i; // Line 78 int k = j + 1; } catch (Exception ex) { // do something // ... PreserveStackTrace(ex); throw; // Line 86 } } /// /// Sets a flag on an so that all the stack trace information is preserved when the exception is re-thrown. /// /// /// This is useful because "throw" removes information, such as the original stack frame. /// See http://dotnetjunkies.com/WebLog/chris.taylor/archive/2004/03/03/8353.aspx for more information on the technique used. /// private static void PreserveStackTrace(Exception exception) { System.Reflection.MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); preserveStackTrace.Invoke(exception, null); } static void Main(string[] args) { //WithThrowEx(); // Line 88 //WithThrow(); // Line 89 //WithThrowIncomplete(); // Line 90 //WithThrowExAndStackTracePreservation(); // Line 91 WithThrowAndStackTracePreservation(); // Line 92 //try //{ // F(); //} //catch (Exception e) //{ // Console.WriteLine("Exception {0} has occured!", e.GetType()); // throw; //Line 104 //} } public static void F() { throw new NotImplementedException("Too lazy to implement!"); } } }