Is there a difference between "throw" and "throw ex"?

Some Posts ask what is the difference between the two.
(Why should I mention this...)

But my problem is different, and what I call "throwing ex" is another wrong way of dealing with images.

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 is used in Main, I will use throw; re-throw the error.But in the simplified code above, all exceptions pass through HandleException

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

#1st floor

The other answers are correct, but I think they provide some extra answers.

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 throw arithExc; 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.

Of course, you've lost information about where the exception occurred.Conversely, if you use throw; 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 much better because now you see that the Program.Div method is causing your problem.However, it is still difficult to see whether the problem comes from line 35 or line 37 in the try block.

If you use the third alternative, packaging in an external exception will not lose any 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 line 35 caused the problem.However, this requires people to search for InnerException and use the internal anomaly feeling a little indirect in a simple case.

stay In this blog post, They preserve the line number (the row of the try block) by calling (reflecting) the internal intance method InternalPreserveStackTrace() on the Exception object.But using this reflection is not good ( .NET Framework may change its internal members without warning at some point).

#2nd floor

Look 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 uses Exception to preserve stack information

This is called "Rethrow"

If you want to throw a new exception,

throw new ApplicationException("operation failed!");

Before throwing:

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

It does not send stack information with exceptions

This is called Breaking the Stack

If you want to throw a new exception,

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

#3rd floor

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 lines 1, 2 and 3 are commented - output - internal before

  2. If all lines 2 and 3 are commented-output-internal ex System.DevideByZeroException: {"Attempt to divide by zero."} ---------

  3. If all lines 1 and 2 are commented - output - internal ex System.Exception:devide by 0 --.

  4. If all lines 1 and 3 are commented-output-internal ex System.DevideByZeroException: {"Attempt to divide by zero."} ---------

If it is throw, the StackTrace is reset;

#4th floor

To give you a different perspective, throw is particularly useful if you provide API s to clients and want to provide detailed stack tracking information to internal libraries.By using throw here, I will get a stack trace of the System.IO.File Library of File.Delete.If I use throw ex, this 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
    }
}

#5th floor

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

To summarize both terms, throw and throw ex are used to understand where the exception occurs.Stack trace throwing an ex override exception regardless of where it was actually thrown.

Let's take an example.

Let's get to know first.

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

The above output is as follows.

Displays the complete hierarchy and method name of the actual exception thrown. It is M2 - > M2.And line number

Second..Let's get to know by throw ex.Simply replace throw with throw ex in the M2 method catch block.Below.

The output of throw ex code is as follows.

You can see the difference in the output.stone ex ignores all previous hierarchies and resets the stack trace using row/method, where throw ex is written.

#6th floor

MSDN representative:

When an exception is thrown, part of the information it carries is the stack trace.Stack tracing is a list of method call hierarchies that start by throwing exceptions and end by capturing exceptions.If an exception is re-thrown by specifying an exception in the throw statement, the stack trace is restarted in the current method, and the list of method calls between the original method that threw the exception and the current method is lost.To preserve the original stack trace information that contains exceptions, use the throw statement without specifying exceptions.

#7th floor

Yes, a little different;

  • throw ex resets stack trace (so your error seems to come from HandleException)
  • throw no - the original criminal will be kept.

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

#8th floor

No, this will cause exceptions to have different stack traces.Using throw only with no exception objects in the catch handler will leave the stack trace unchanged.

You may want to return a Boolean value from HandleException, regardless of whether or not the exception is thrown again.

#9th floor

When an ex is thrown, the thrown exception becomes a "raw" exception.All previous stack traces will not exist.

If you do throw, then the exception is only online and you will get a complete stack trace.

#10th floor

(I sent it before, @ Marc Gravell corrected me)

Here is 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
}

This 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 returns to the DivByZero() method, but not in exception 2.

Note, however, that the line numbers shown in ThrowException1() and ThrowException2() are the line numbers of the throw statement, not the line numbers called on DivByZero(), which may make sense because I think it's a bit...

Output in Publish 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)

Does it maintain the original stackTrace only in debug mode?

0 original articles published. 2. 10,000 visits+
Private letter follow

Posted on Fri, 07 Feb 2020 20:36:56 -0800 by jasonmills58