In C++, Is There a Difference Between "Throw" and "Throw Ex"

Not finding any difference between throw vs throw ex in C#

The problem that you're not seeing is that the possible throw locations you're working with are so close together as to be indistinguishable when the stack trace is collected.

Try instead:

public void Test()
{
try
{
Deeper();
}
catch (Exception ex)
{

throw; //throw statement
}
}

private static void Deeper()
{
int a = 10;
int b = 10;
int c = 10 / (a - b);
}

The throw; variant will show you Deeper in the stack trace. throw ex; will only show Test as the deepest level.

Is there a difference between throw and throw ex?

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;
    }
    }

In C++, is there a difference between “throw” and “throw ex”?

throw; rethrows the same exception object it caught while throw ex; throws a new exception. It does not make a difference other than the performance reasons of creating a new exception object. If you have a exception hierarchy where there some other exception classes derived from MyException class and while throwing an exception you have done a throw DerivedClassException; it can be caught by the catch(MyException&). Now if you modify this caught exception object and rethrow it using throw; the type of exception object will still be DerivedClassException. If you do throw Ex; the object slicing occurs and the newly thrown exception will be of type MyException.

Difference between 'throw' and 'throw new Exception()'

throw; rethrows the original exception and preserves its original stack trace.

throw ex; throws the original exception but resets the stack trace, destroying all stack trace information until your catch block.



NEVER write throw ex;


throw new Exception(ex.Message); is even worse. It creates a brand new Exception instance, losing the original stack trace of the exception, as well as its type. (eg, IOException).

In addition, some exceptions hold additional information (eg, ArgumentException.ParamName).

throw new Exception(ex.Message); will destroy this information too.

In certain cases, you may want to wrap all exceptions in a custom exception object, so that you can provide additional information about what the code was doing when the exception was thrown.

To do this, define a new class that inherits Exception, add all four exception constructors, and optionally an additional constructor that takes an InnerException as well as additional information, and throw your new exception class, passing ex as the InnerException parameter. By passing the original InnerException, you preserve all of the original exception's properties, including the stack trace.

Why do throw and throw ex have the same behavior in this case?

Note: This answer is for .NET Framework. You might observe a different behavior if you're using .NET Core or .NET 5.0 and above, as mentioned in the comments. I did not test on all versions of .NET Core


Okay, let me take a stab at it. The difference between throw and throw ex is already explained in Is there a difference between "throw" and "throw ex"? but I'll try to put it in more clear terms to fit the narrative of this question.

  • throw ex: Rethrows the exception from this point and resets the stack trace.

  • throw: Rethrows the exception from this point and preserves the stack trace.

Let's look at the code in question:

private static void DummyWork()
{
try
{
throw new Exception("dummy"); // Line 21
}
catch (Exception ex)
{
throw; // Line 25
}
}

Here, whether we use throw or throw ex, the stack trace will always be:

at Program.DummyWork() in ...:line 25
at Program.Main() in ...:line 9

Q: Why "line 25"?

A: Because both throw and throw ex rethrow the exception from that point.

Q: Why is there no difference in this case?

A: Because there aren't any more stack frames in the stack trace to reset.

Q: How can we see the difference?

Well, let's add another level to generate another stack frame. The code would be something like this:

private static void DummyWork()
{
try
{
MoreDummyWork(); // Line 21
}
catch (Exception ex)
{
throw; //Line 25
}
}

private static void MoreDummyWork()
{
throw new Exception("dummy"); // Line 31
}

Here, we can clearly see the difference. If we use throw, the stack trace is the following:

at Program.MoreDummyWork() in ...:line 31
at Program.DummyWork() in ...:line 25
at Program.Main() in ...:line 9

But if we use throw ex, the stack trace becomes:

at Program.DummyWork() in ...:line 25
at Program.Main() in ...:line 9

Q: Okay, you say both will throw the exception from that point. What if I want to maintain the original line number?

A: In this case, you can use ExceptionDispatchInfo.Capture(ex).Throw(); as explained in How to rethrow InnerException without losing stack trace in C#?:

Why do throw and throw ex in a catch block behave the same way?

throw will only preserve the stack frame if you don't throw it from within the current one. You're doing just that by doing all of this in one method.

See this answer: https://stackoverflow.com/a/5154318/1517578

PS: +1 for asking a question that was actually a valid question.

What is the difference between throw and throw with arg of caught exception?

Depending on how you have arranged your exception hierarchy, re-throwing an exception by naming the exception variable in the throw statement may slice the original exception object.

A no-argument throw expression will throw the current exception object preserving its dynamic type, whereas a throw expression with an argument will throw a new exception based on the static type of the argument to throw.

E.g.

int main()
{
try
{
try
{
throw Derived();
}
catch (Base& b)
{
std::cout << "Caught a reference to base\n";
b.print(std::cout);
throw b;
}
}
catch (Base& b)
{
std::cout << "Caught a reference to base\n";
b.print(std::cout);
}

return 0;
}

As written above, the program will output:

Caught a reference to base
Derived
Caught a reference to base
Base

If the throw b is replace with a throw, then the outer catch will also catch the originally thrown Derived exception. This still holds if the inner class catches the Base exception by value instead of by reference - although naturally this would mean that the original exception object cannot be modified, so any changes to b would not be reflected in the Derived exception caught by the outer block.



Related Topics



Leave a reply



Submit