Coder Perfect

‘throw’ and ‘throw new Exception()’ are two different things.

Problem

What is the distinction between the two?

try { ... }
catch{ throw }

and

try{ ... }
catch(Exception e) {throw new Exception(e.message) }

Regardless of the fact that the second displays a message.

Asked by Strider007

Solution #1

throw; rethrows the original exception with the original stack trace preserved.

throw ex; fires the original exception but resets the stack trace, erasing all stack trace data until your catch block is executed.

Even worse, throw new Exception(ex.Message); It produces a new Exception instance, discarding the exception’s original stack trace as well as its type. (For example, IOException). Furthermore, certain exceptions contain additional data (eg, ArgumentException.ParamName). This information will be destroyed as well if you throw new Exception(ex.Message).

You might want to wrap all exceptions in a custom exception object in some circumstances to provide more information about what the code was doing when the exception was thrown.

To do so, create a new class that derives from Exception, add all four exception constructors, as well as an optional additional function Object() { [native code] } that accepts an InnerException and additional information, and throw your new exception class, passing ex as the InnerException parameter. You can keep all of the original exception’s attributes, including the stack trace, by supplying the original InnerException.

Answered by SLaks

Solution #2

The first keeps the stacktrace in tact:

try { ... }
catch
{
    // Do something.
    throw;
}

The second lets you adjust the exception’s type, as well as the message and other data:

try { ... } catch (Exception e)
{
    throw new BarException("Something broke!");
}

There’s a third option for passing an inner exception:

try { ... }
catch (FooException e) {
    throw new BarException("foo", e);
} 

I’d recommend using:

Answered by Mark Byers

Solution #3

Another aspect I didn’t hear anyone mention:

Having a try…catch is meaningless if you don’t do anything in your catch block. This is something I see all the time:

try 
{
  //Code here
}
catch
{
    throw;
}

Or worse:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw ex;
}

Worst yet:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw new System.Exception(ex.Message);
}

Answered by Marcie

Solution #4

The current stack trace is obliterated when a new Exception is thrown.

toss; preserves the stack trace and is almost always more useful. The only exception to this rule is if you want to wrap the Exception in your own custom Exception. After that, you should:

catch(Exception e)
{
    throw new CustomException(customMessage, e);
}

Answered by Justin Niessner

Solution #5

None of the answers here show the difference, which could be useful for those who are having trouble understanding it. Consider the following code:

using System;
using System.Collections.Generic;

namespace ExceptionDemo
{
   class Program
   {
      static void Main(string[] args)
      {
         void fail()
         {
            (null as string).Trim();
         }

         void bareThrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw;
            }
         }

         void rethrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw e;
            }
         }

         void innerThrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw new Exception("outer", e);
            }
         }

         var cases = new Dictionary<string, Action>()
         {
            { "Bare Throw:", bareThrow },
            { "Rethrow", rethrow },
            { "Inner Throw", innerThrow }
         };

         foreach (var c in cases)
         {
            Console.WriteLine(c.Key);
            Console.WriteLine(new string('-', 40));
            try
            {
               c.Value();
            } catch (Exception e)
            {
               Console.WriteLine(e.ToString());
            }
         }
      }
   }
}

As a result, you’ll get the following:

Bare Throw:
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
   at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
   at ExceptionDemo.Program.<>c.<Main>g__bareThrow|0_1() in C:\...\ExceptionDemo\Program.cs:line 19
   at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64

Rethrow
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
   at ExceptionDemo.Program.<>c.<Main>g__rethrow|0_2() in C:\...\ExceptionDemo\Program.cs:line 35
   at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64

Inner Throw
----------------------------------------
System.Exception: outer ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
   at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 43
   --- End of inner exception stack trace ---
   at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 47
   at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64

The raw throw clearly indicates both the initial line of code that failed (line 12) as well as the two other places active in the call stack when the exception occurred, as described in the prior responses (lines 19 and 64).

The rethrow case’s output demonstrates why this is a problem. When an exception is rethrown in this manner, the original stack information is not included. Only the throw e (line 35) and the outermost call stack point (line 64) are included in this example. If you throw exceptions this manner, it will be difficult to track down the fail() method as the root of the problem.

The last example (innerThrow) is the most detailed and contains more information than the previous two. We can add contextual information (the “outer” message, here, but we can also contribute to the ) because we’re creating a new exception. On the new exception, a data dictionary is created, as well as all of the information from the original exception is preserved (including help links, data dictionary, etc.).

Answered by Lee

Post is based on https://stackoverflow.com/questions/2999298/difference-between-throw-and-throw-new-exception