2

What are the best practices for choosing between throw; and throw ex;? Is there any at all? Regarding, for example, this simple snippet:

try{
    // some code
} catch (Exception ex) {
    // some catcher code
    // throw; ?
    // or
    // throw ex; ?
    // how to decide which one?
}

I know the difference between the two above. How can I decide to use one of them? Is there a best practice to making a better choice?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
amiry jd
  • 27,021
  • 30
  • 116
  • 215
  • 2
    Use `throw`, this keeps the original stacktrace. But why would you catch a general exception at all? Seems to me you cannot handle it, so why catch it? – Maarten Aug 18 '16 at 14:03
  • @Maarten it would happen sometimes. retrying of some operations for example – amiry jd Aug 18 '16 at 14:06
  • Possible duplicate of [Is there a difference between "throw" and "throw ex"?](http://stackoverflow.com/questions/730250/is-there-a-difference-between-throw-and-throw-ex) – Sinatr Aug 18 '16 at 15:02
  • @Sinatr see the update please. Thank you in advance. – amiry jd Aug 18 '16 at 15:12

2 Answers2

8

You should either use throw; to rethrow the original exception (with the original stack trace) or use throw new MyException(..., ex); to throw your own exception that may provide additional information and set the inner exception to ex.

If you don't have any additional information, just use throw;.

If you only catch the exception to do cleanup, then use try {...} finally {...} instead.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
P. Kouvarakis
  • 1,893
  • 12
  • 21
1

It's very simple.

Do you want to keep the stack trace to see exactly where the exception occurs? Then use throw. This will be like if you don't use catch at all.

Do you only care about the current method's debug information? Then use throw ex.

To demonstrate:

static void Main(string[] args)
{
    try
    {
        Test();
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}

static void Test()
{
    try
    {
        // long lambda chain
        new Action(() => new Action(() => new Action(() => { throw new InvalidOperationException(); })())())();
    }
    catch (Exception ex)
    {
        //throw;
        //throw ex;
    }
}

throw will keep the stack trace:

System.InvalidOperationException: Operation is not valid due to the current state of the object.
    at ConsoleApplication.Program.<>c.<Test>b__1_2() in ConsoleApplication\Program.cs:line 22
    at ConsoleApplication.Program.<>c.<Test>b__1_1() in ConsoleApplication\Program.cs:line 22
    at ConsoleApplication.Program.<>c.<Test>b__1_0() in ConsoleApplication\Program.cs:line 22
    at ConsoleApplication.Program.Test() in ConsoleApplication\Program.cs:line 26
    at ConsoleApplication.Program.Main(String[] args) in ConsoleApplication\Program.cs:line 13

throw ex will reset stack trace:

System.InvalidOperationException: Operation is not valid due to the current state of the object.
    at ConsoleApplication.Program.Test() in ConsoleApplication\Program.cs:line 27
    at ConsoleApplication.Program.Main(String[] args) in ConsoleApplication\Program.cs:line 13

As for best practices - the choice is usually throw. As a developer, you want to get as much information as you can. throw ex is a counterpart - some information is hidden, but maybe you want to hide it, who knows?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sinatr
  • 20,892
  • 15
  • 90
  • 319