有一些帖子问这两者之间已经有什么区别了。(为什么我要提这个…)

但我的问题在某种程度上是不同的,我在另一种错误处理方法中调用了“throw ex”。

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

如果在主线中使用try和catch,那么我会使用throw;重新抛出错误。 但是在上面的简单代码中,所有异常都通过HandleException

是否抛出前任;在HandleException内部调用时,与调用throw有相同的效果?


当前回答

Throw保存堆栈跟踪。假设Source1抛出Error1,它被Source2捕获,而Source2表示抛出,那么在堆栈跟踪中Source1 Error + Source2 Error将可用。

Throw ex不保留堆栈跟踪。因此Source1的所有错误将被清除,只有Source2的错误将被发送到客户端。

有时只是阅读的东西不清楚,建议看这个视频演示,以获得更清楚,在c# Throw vs Throw ex。

其他回答

是的,这是有区别的。

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

Throw保存堆栈跟踪。假设Source1抛出Error1,它被Source2捕获,而Source2表示抛出,那么在堆栈跟踪中Source1 Error + Source2 Error将可用。

Throw ex不保留堆栈跟踪。因此Source1的所有错误将被清除,只有Source2的错误将被发送到客户端。

有时只是阅读的东西不清楚,建议看这个视频演示,以获得更清楚,在c# Throw vs Throw ex。

最好使用throw而不是throw ex。

Throw ex重置原始堆栈跟踪,无法找到之前的堆栈跟踪。

如果使用throw,我们将得到一个完整的堆栈跟踪。

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、2和3行都注释了- 输出-内ex 如果所有第2行和第3行都注释了- 输出-内ex 系统。DevideByZeroException:{"试图除零。"}--------- 如果所有第1行和第2行都注释了- 输出-内ex 系统。例外:除0 ---- 如果所有第1行和第3行都注释了- 输出-内ex 系统。DevideByZeroException:{"试图除零。"}---------

和StackTrace将重置的情况下抛出ex;

(我之前发过,@Marc Gravell纠正了我)

以下是其中的区别:

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
}

这是输出:

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

您可以看到,在例外1中,堆栈跟踪返回到DivByZero()方法,而在例外2中则没有。

但是请注意,在ThrowException1()和ThrowException2()中显示的行号是throw语句的行号,而不是调用DivByZero()的行号,现在我稍微思考一下,这可能是有意义的……

释放模式输出

例外1:

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

例外2:

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

它是否只在调试模式下维护原始的stackTrace ?