By dance2die


2009-04-08 14:22:12 8 Comments

There are some posts that asks what the difference between those two are already.
(why do I have to even mention this...)

But my question is different in a way that I am calling "throw ex" in another error god-like handling method.

public class Program {
    public static void Main(string[] args) {
        try {
            // something
        } catch (Exception ex) {
            HandleException(ex);
        }
    }

    private static void HandleException(Exception ex) {
        if (ex is ThreadAbortException) {
            // ignore then,
            return;
        }
        if (ex is ArgumentOutOfRangeException) { 
            // Log then,
            throw ex;
        }
        if (ex is InvalidOperationException) {
            // Show message then,
            throw ex;
        }
        // and so on.
    }
}

If try & catch were used in the Main, then I would use throw; to rethrow the error. But in the above simplied code, all exceptions go through HandleException

Does throw ex; has the same effect as calling throw when called inside HandleException?

10 comments

@Marc Gravell 2009-04-08 14:24:56

Yes, there is a difference;

  • throw ex resets the stack trace (so your errors would appear to originate from HandleException)
  • throw doesn't - the original offender would be preserved.

    static void Main(string[] args)
    {
        try
        {
            Method2();
        }
        catch (Exception ex)
        {
            Console.Write(ex.StackTrace.ToString());
            Console.ReadKey();
        }
    }
    
    private static void Method2()
    {
        try
        {
            Method1();
        }
        catch (Exception ex)
        {
            //throw ex resets the stack trace Coming from Method 1 and propogates it to the caller(Main)
            throw ex;
        }
    }
    
    private static void Method1()
    {
        try
        {
            throw new Exception("Inside Method1");
        }
        catch (Exception)
        {
            throw;
        }
    }
    

@Scott Dorman 2009-04-08 14:38:48

To expand on Marc's answer a bit, you can find more details here: geekswithblogs.net/sdorman/archive/2007/08/20/…

@dance2die 2009-04-08 16:22:21

@Scott: Thank you for the link. And I have also found out about how to extract error handler in the follow-up question: stackoverflow.com/questions/730300/…

@Shaul says I Support Monica 2009-04-22 11:28:49

This answer is incorrect! See stackoverflow.com/questions/730300/…

@Marc Gravell 2009-04-22 12:05:09

@Shaul; no, it isn't. I've given details in a comment to your post.

@Shaul says I Support Monica 2009-04-22 18:08:22

@Marc Gravell - my apologies, you were right. Sorry about the downvote; it's too late for me to undo... :(

@Brann 2011-03-01 09:17:14

@Marc : It seems that throw preserves the original offender ONLY if the throw isn't in the method in which the initial exception was thrown (see this question : stackoverflow.com/questions/5152265/… )

@JonH 2012-05-29 20:37:41

@Xenan - you aren't the only one - I always get it mixed up too. It just looks strange.

@Jeppe Stig Nielsen 2012-06-27 15:34:00

If you modify the object referenced by ex, for example by setting the ex.HelpLink property, this is reflected with both throw; and throw ex;. If, on the other hand, you assign to the ex variable (to make it reference another object), then clearly throw; will use the original object, while throw ex; will use the new object. It is also interesting to note that even if you use the preferred throw; variant, you lose information about the line number inside the try block. I just wrote a new answer about that (see also the answer of @Shaul ).

@Marc Gravell 2012-06-27 15:35:41

@Jeppe to be fair the question clearly doesn't show a reassignment to ex

@Jeppe Stig Nielsen 2012-06-27 20:40:57

No, you're right. In that case throw; and throw ex; throw the same object, but its stack trace is modified in different way, as you explain in your answer.

@Learner 2013-03-01 17:36:56

@Xenan: WYSIWYG - Microsoft Visual Studio editor. And even, I have just experimented throw and throw ex, as its understood by all, throw is the better option as it gives the information from the source of exception. I really wonder why you bring up things which is not necessary. What you see in the output (The real message is what we should be worrying about). I do not understand why do you bring up MSIL part and all here or how it makes sense for optimization.

@xr280xr 2019-08-24 02:59:56

I've just read that a benefit of exception filters is that you can avoid unwinding the stack because a catch always unwinds the stack even if you just throw; the exception. Is that different from what you are talking about here with preserving the stack trace? When I first read this a couple months ago I thought that is what you meant or they were one in the same.

@Marc Gravell 2019-08-25 17:38:02

@xr280xr not what I was talking about, but an interesting question

@xr280xr 2019-08-26 20:37:16

So it is simply the value of the StackTrace property that is not preserved but in both cases [thomaslevesque.com/2015/06/21/exception-filters-in-c-6/](th‌​e stack is unwound). Seems like a strange, and unintuitive design choice for the StackTrace. Thanks for pointing it out.

@ruffin 2019-10-08 21:21:22

@ScottDorman Looks like your link isn't being forwarded correctly after a blog migration. Looks like it now lives here. Edit: Hey, wait, that's your blog! Fix your own links! ;^D

@Jeppe Stig Nielsen 2012-06-27 15:26:48

The other answers are entirely correct, but this answer provides some extra detalis, I think.

Consider this example:

using System;

static class Program {
  static void Main() {
    try {
      ThrowTest();
    } catch (Exception e) {
      Console.WriteLine("Your stack trace:");
      Console.WriteLine(e.StackTrace);
      Console.WriteLine();
      if (e.InnerException == null) {
        Console.WriteLine("No inner exception.");
      } else {
        Console.WriteLine("Stack trace of your inner exception:");
        Console.WriteLine(e.InnerException.StackTrace);
      }
    }
  }

  static void ThrowTest() {
    decimal a = 1m;
    decimal b = 0m;
    try {
      Mult(a, b);  // line 34
      Div(a, b);   // line 35
      Mult(b, a);  // line 36
      Div(b, a);   // line 37
    } catch (ArithmeticException arithExc) {
      Console.WriteLine("Handling a {0}.", arithExc.GetType().Name);

      //   uncomment EITHER
      //throw arithExc;
      //   OR
      //throw;
      //   OR
      //throw new Exception("We handled and wrapped your exception", arithExc);
    }
  }

  static void Mult(decimal x, decimal y) {
    decimal.Multiply(x, y);
  }
  static void Div(decimal x, decimal y) {
    decimal.Divide(x, y);
  }
}

If you uncomment the throw arithExc; line, your output is:

Handling a DivideByZeroException.
Your stack trace:
   at Program.ThrowTest() in c:\somepath\Program.cs:line 44
   at Program.Main() in c:\somepath\Program.cs:line 9

No inner exception.

Certainly, you have lost information about where that exception happened. If instead you use the throw; line, this is what you get:

Handling a DivideByZeroException.
Your stack trace:
   at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
   at System.Decimal.Divide(Decimal d1, Decimal d2)
   at Program.Div(Decimal x, Decimal y) in c:\somepath\Program.cs:line 58
   at Program.ThrowTest() in c:\somepath\Program.cs:line 46
   at Program.Main() in c:\somepath\Program.cs:line 9

No inner exception.

This is a lot better, because now you see that it was the Program.Div method that caused you problems. But it's still hard to see if this problem comes from line 35 or line 37 in the try block.

If you use the third alternative, wrapping in an outer exception, you lose no information:

Handling a DivideByZeroException.
Your stack trace:
   at Program.ThrowTest() in c:\somepath\Program.cs:line 48
   at Program.Main() in c:\somepath\Program.cs:line 9

Stack trace of your inner exception:
   at System.Decimal.FCallDivide(Decimal& d1, Decimal& d2)
   at System.Decimal.Divide(Decimal d1, Decimal d2)
   at Program.Div(Decimal x, Decimal y) in c:\somepath\Program.cs:line 58
   at Program.ThrowTest() in c:\somepath\Program.cs:line 35

In particular you can see that it's line 35 that leads to the problem. However, this requires people to search the InnerException, and it feels somewhat indirect to use inner exceptions in simple cases.

In this blog post they preserve the line number (line of the try block) by calling (through reflection) the internal intance method InternalPreserveStackTrace() on the Exception object. But it's not nice to use reflection like that (the .NET Framework might change their internal members some day without warning).

@Bhanu pratap 2016-12-01 08:49:44

int a = 0;
try {
    int x = 4;
    int y ;
    try {
        y = x / a;
    } catch (Exception e) {
        Console.WriteLine("inner ex");
        //throw;   // Line 1
        //throw e;   // Line 2
        //throw new Exception("devide by 0");  // Line 3
    }
} catch (Exception ex) {
    Console.WriteLine(ex);
    throw ex;
}
  1. if all Line 1 ,2 and 3 are commented - Output - inner ex

  2. if all Line 2 and 3 are commented - Output - inner ex System.DevideByZeroException: {"Attempted to divide by zero."}---------

  3. if all Line 1 and 2 are commented - Output - inner ex System.Exception: devide by 0 ----

  4. if all Line 1 and 3 are commented - Output - inner ex System.DevideByZeroException: {"Attempted to divide by zero."}---------

and StackTrace will be reset in case of throw ex;

@Charles Owen 2017-02-01 07:04:12

To give you a different perspective on this, using throw is particularly useful if you're providing an API to a client and you want to provide verbose stack trace information for your internal library. By using throw here, I'd get the stack trace in this case of the System.IO.File library for File.Delete. If I use throw ex, then that information will not be passed to my handler.

static void Main(string[] args) {            
   Method1();            
}

static void Method1() {
    try {
        Method2();
    } catch (Exception ex) {
        Console.WriteLine("Exception in Method1");             
    }
}

static void Method2() {
    try {
        Method3();
    } catch (Exception ex) {
        Console.WriteLine("Exception in Method2");
        Console.WriteLine(ex.TargetSite);
        Console.WriteLine(ex.StackTrace);
        Console.WriteLine(ex.GetType().ToString());
    }
}

static void Method3() {
    Method4();
}

static void Method4() {
    try {
        System.IO.File.Delete("");
    } catch (Exception ex) {
        // Displays entire stack trace into the .NET 
        // or custom library to Method2() where exception handled
        // If you want to be able to get the most verbose stack trace
        // into the internals of the library you're calling
        throw;                
        // throw ex;
        // Display the stack trace from Method4() to Method2() where exception handled
    }
}

@Aaaaaaaa 2014-07-18 20:33:08

Look at here: http://blog-mstechnology.blogspot.de/2010/06/throw-vs-throw-ex.html

Throw:

try 
{
    // do some operation that can fail
}
catch (Exception ex)
{
    // do some local cleanup
    throw;
}

It preserve the Stack information with Exception

This is called as "Rethrow"

If want to throw new exception,

throw new ApplicationException("operation failed!");

Throw Ex:

try
{
    // do some operation that can fail
}
catch (Exception ex)
{
    // do some local cleanup
    throw ex;
}

It Won't Send Stack information with Exception

This is called as "Breaking the Stack"

If want to throw new exception,

throw new ApplicationException("operation failed!",ex);

@Mahesh 2017-12-05 11:50:24

let's understand the difference between throw and throw ex. I heard that in many .net interviews this common asked is being asked.

Just to give an overview of these two terms, throw and throw ex are both used to understand where the exception has occurred. Throw ex rewrites the stack trace of exception irrespective where actually has been thrown.

Let's understand with an example.

Let's understand first Throw.

static void Main(string[] args) {
    try {
        M1();
    } catch (Exception ex) {
        Console.WriteLine(" -----------------Stack Trace Hierarchy -----------------");
        Console.WriteLine(ex.StackTrace.ToString());
        Console.WriteLine(" ---------------- Method Name / Target Site -------------- ");
        Console.WriteLine(ex.TargetSite.ToString());
    }
    Console.ReadKey();
}

static void M1() {
    try {
        M2();
    } catch (Exception ex) {
        throw;
    };
}

static void M2() {
    throw new DivideByZeroException();
}

output of the above is below.

shows complete hierarchy and method name where actually the exception has thrown.. it is M2 -> M2. along with line numbers

enter image description here

Secondly.. lets understand by throw ex. Just replace throw with throw ex in M2 method catch block. as below.

enter image description here

output of throw ex code is as below..

enter image description here

You can see the difference in the output.. throw ex just ignores all the previous hierarchy and resets stack trace with line/method where throw ex is written.

@Mudassir Hasan 2018-02-07 13:10:00

best answer,....

@Shaul says I Support Monica 2009-04-22 11:29:47

(I posted earlier, and @Marc Gravell has corrected me)

Here's a demonstration of the difference:

static void Main(string[] args) {
    try {
        ThrowException1(); // line 19
    } catch (Exception x) {
        Console.WriteLine("Exception 1:");
        Console.WriteLine(x.StackTrace);
    }
    try {
        ThrowException2(); // line 25
    } catch (Exception x) {
        Console.WriteLine("Exception 2:");
        Console.WriteLine(x.StackTrace);
    }
}

private static void ThrowException1() {
    try {
        DivByZero(); // line 34
    } catch {
        throw; // line 36
    }
}
private static void ThrowException2() {
    try {
        DivByZero(); // line 41
    } catch (Exception ex) {
        throw ex; // line 43
    }
}

private static void DivByZero() {
    int x = 0;
    int y = 1 / x; // line 49
}

and here is the output:

Exception 1:
   at UnitTester.Program.DivByZero() in <snip>\Dev\UnitTester\Program.cs:line 49
   at UnitTester.Program.ThrowException1() in <snip>\Dev\UnitTester\Program.cs:line 36
   at UnitTester.Program.TestExceptions() in <snip>\Dev\UnitTester\Program.cs:line 19

Exception 2:
   at UnitTester.Program.ThrowException2() in <snip>\Dev\UnitTester\Program.cs:line 43
   at UnitTester.Program.TestExceptions() in <snip>\Dev\UnitTester\Program.cs:line 25

You can see that in Exception 1, the stack trace goes back to the DivByZero() method, whereas in Exception 2 it does not.

Take note, though, that the line number shown in ThrowException1() and ThrowException2() is the line number of the throw statement, not the line number of the call to DivByZero(), which probably makes sense now that I think about it a bit...

Output in Release mode

Exception 1:

at ConsoleAppBasics.Program.ThrowException1()
at ConsoleAppBasics.Program.Main(String[] args)

Exception 2:

at ConsoleAppBasics.Program.ThrowException2()
at ConsoleAppBasics.Program.Main(String[] args)

Is it maintains the original stackTrace in debug mode only?

@Menahem 2016-09-08 14:23:03

Its because the compiler's optimization process inlines short methods such as DevideByZero, so the stack trace IS the same. maybe you should post this as a question on it`s own

@A.S. 2018-04-06 13:30:18

MSDN stands for:

Once an exception is thrown, part of the information it carries is the stack trace. The stack trace is a list of the method call hierarchy that starts with the method that throws the exception and ends with the method that catches the exception. If an exception is re-thrown by specifying the exception in the throw statement, the stack trace is restarted at the current method and the list of method calls between the original method that threw the exception and the current method is lost. To keep the original stack trace information with the exception, use the throw statement without specifying the exception.

@GR7 2009-04-08 14:27:11

When you do throw ex, that exception thrown becomes the "original" one. So all previous stack trace will not be there.

If you do throw, the exception just goes down the line and you'll get the full stack trace.

@Lucero 2009-04-08 14:26:59

No, this will cause the exception to have a different stack trace. Only using a throw without any exception object in the catch handler will leave the stack trace unchanged.

You may want to return a boolean from HandleException whether the exception shall be rethrown or not.

Related Questions

Sponsored Content

32 Answered Questions

[SOLVED] The case against checked exceptions

14 Answered Questions

[SOLVED] Difference Between Select and SelectMany

  • 2009-06-06 03:54:16
  • Tarik
  • 469591 View
  • 986 Score
  • 14 Answer
  • Tags:   c# linq-to-sql linq

13 Answered Questions

[SOLVED] How do you test that a Python function throws an exception?

6 Answered Questions

[SOLVED] Globally catch exceptions in a WPF application?

32 Answered Questions

[SOLVED] What is the difference between const and readonly in C#?

65 Answered Questions

[SOLVED] What is the difference between String and string in C#?

7 Answered Questions

[SOLVED] Manually raising (throwing) an exception in Python

  • 2010-01-12 21:07:40
  • TIMEX
  • 1596448 View
  • 2070 Score
  • 7 Answer
  • Tags:   python exception

31 Answered Questions

[SOLVED] What is the difference between a field and a property?

  • 2008-11-17 08:41:38
  • Anonymous
  • 413705 View
  • 1028 Score
  • 31 Answer
  • Tags:   c# properties field

16 Answered Questions

[SOLVED] Difference between decimal, float and double in .NET?

6 Answered Questions

[SOLVED] Which part of throwing an Exception is expensive?

Sponsored Content