有一些帖子询问这两者之间的区别是什么 .
(为什么我还要提这个......)
但我的问题是不同的,我称之为"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.
}
}
如果在 Main
中使用了 try & catch
,那么我将使用 throw;
来重新抛出错误 . 但是在上面简化的代码中,所有异常都经过 HandleException
在 HandleException
中调用 throw ex;
与调用 throw
具有相同的效果吗?
10 回答
让我们理解throw和throw ex之间的区别 . 我听说在很多.net采访中都会被问到这个常见问题 .
为了概括这两个术语,throw和throw ex都用于了解异常发生的位置 . 抛出ex重写异常的堆栈跟踪,而不管实际抛出的位置 .
让我们通过一个例子来理解 .
让我们先了解一下 .
以上输出如下 .
显示实际抛出异常的完整层次结构和方法名称..它是M2 - > M2 . 以及行号
其次..让我们通过throw ex了解 . 在M2方法catch块中用throw ex替换throw . 如下 .
throw ex代码的输出如下 .
您可以看到输出中的差异.leve ex忽略所有先前的层次结构,并使用行/方法重置堆栈跟踪,其中写入了throw ex .
抛出ex时,抛出的异常变为“原始”异常 . 所以之前的所有堆栈跟踪都不会存在 .
如果你做了抛出,那么异常只是在线上,你将获得完整的堆栈跟踪 .
看这里:http://blog-mstechnology.blogspot.de/2010/06/throw-vs-throw-ex.html
Throw :
它使用Exception保留堆栈信息
这被称为“Rethrow”
如果想抛出新的异常,
Throw Ex :
它不会发送带有异常的堆栈信息
这被称为“打破堆栈”
如果想抛出新的异常,
不,这将导致异常具有不同的堆栈跟踪 . 只在
catch
处理程序中使用throw
而没有任何异常对象将使堆栈跟踪保持不变 .您可能希望从HandleException返回一个布尔值,无论是否重新抛出异常 .
其他答案完全正确,但我认为这个答案提供了一些额外的答案 .
考虑这个例子:
如果取消注释
throw arithExc;
行,则输出为:当然,您丢失了有关该异常发生位置的信息 . 相反,如果你使用
throw;
行,这就是你得到的:这样做要好得多,因为现在你看到
Program.Div
方法导致了你的问题 . 但是仍然很难看出这个问题是来自try
块中的第35行还是第37行 .如果您使用第三个替代方法,包装在外部异常中,则不会丢失任何信息:
特别是你可以看到导致问题的是 line 35 . 但是,这需要人们搜索
InnerException
,并且在简单情况下使用内部异常感觉有点间接 .在this blog post中,它们通过在
Exception
对象上调用(通过反射)internal
intance方法InternalPreserveStackTrace()
来保留行号(try块的行) . 但是使用这样的反射并不好(.NET Framework可能会在某天没有警告的情况下改变它们的internal
成员) .是,有一点不同;
throw ex
重置堆栈跟踪(因此您的错误似乎来自HandleException
)throw
没有 - 原始罪犯将被保留 .MSDN stands for :
为了给您一个不同的视角,如果您向客户端提供API并且想要为内部库提供详细的堆栈跟踪信息,则使用throw特别有用 . 通过在这里使用throw,我将获得File.Delete的System.IO.File库的堆栈跟踪 . 如果我使用throw ex,那么该信息将不会传递给我的处理程序 .
(我之前发过,@ Marc Gravell纠正了我)
以下是对差异的演示:
这是输出:
您可以在异常1中看到堆栈跟踪返回到
DivByZero()
方法,而在例外2中它没有 .但请注意,
ThrowException1()
和ThrowException2()
中显示的行号是throw
语句的行号, not 是DivByZero()
调用的行号,这可能是有道理的,因为我现在考虑一下......在发布模式下输出
例外1:
例外2:
它是否仅在调试模式下维护原始的stackTrace?
如果所有第1,2和3行都被注释 - 输出 - 内部前
如果所有第2行和第3行都被注释 - 输出 - 内部ex System.DevideByZeroException:{“试图除以零 . ”} ---------
如果所有第1行和第2行都被注释 - 输出 - 内部ex System.Exception:devide by 0 ----
如果所有第1行和第3行都被注释 - 输出 - 内部ex System.DevideByZeroException:{“试图除以零 . ”} ---------
如果是throw ex,则会重置StackTrace;