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

但我的问题在某种程度上是不同的,我在另一种错误处理方法中调用了“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而不是throw ex。

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

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

其他回答

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

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

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

看这里:http://blog-mstechnology.blogspot.de/2010/06/throw-vs-throw-ex.html

把:

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

它保留了异常堆栈信息

这叫做"重扔"

如果想要抛出新的异常,

throw new ApplicationException("operation failed!");

把交货:

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

它不会发送异常堆栈信息

这叫做“打破堆栈”

如果想要抛出新的异常,

throw new ApplicationException("operation failed!",ex);
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;

为了扩展Lucero的回答,下面介绍如何在不丢失原始堆栈跟踪的情况下实现原始代码的意图。

public class Program {
    public static void Main(string[] args) {
        try {
            // something
        } catch (Exception ex) {
            if (!HandleException(ex)) throw;
        }
    }

    /// <returns>
    ///   true if the exception has been handled;
    ///   false if exception should be passed along
    /// </returns>
    private static bool HandleException(Exception ex) {
        if (ex is ThreadAbortException) {
            // ignore then,
            return true;
        }
        if (ex is ArgumentOutOfRangeException) { 
            // Log then,
            return false;
        }
        if (ex is InvalidOperationException) {
            // Show message then,
            return false;
        }
        // and so on.
    }
}

微软文档代表:

Once an exception is thrown, part of the information it carries is the stack trace. The stack trace is a list of the method call hierarchy that starts with the method that throws the exception and ends with the method that catches the exception. If an exception is re-thrown by specifying the exception in the throw statement, the stack trace is restarted at the current method and the list of method calls between the original method that threw the exception and the current method is lost. To keep the original stack trace information with the exception, use the throw statement without specifying the exception.

来源:https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2200