捕获异常并重新抛出异常时需要考虑哪些最佳实践?我想确保保留Exception
对象InnerException
和堆栈跟踪.以下代码块在处理此方式时是否存在差异?
try
{
//some code
}
catch (Exception ex)
{
throw ex;
}
Run Code Online (Sandbox Code Playgroud)
VS:
try
{
//some code
}
catch
{
throw;
}
Run Code Online (Sandbox Code Playgroud) catch中的以下append()是否会导致重新抛出的异常以查看append()被调用的效果?
try {
mayThrowMyErr();
} catch (myErr &err) {
err.append("Add to my message here");
throw; // Does the rethrow exception reflect the call to append()?
}
Run Code Online (Sandbox Code Playgroud)
类似地,如果我以这种方式重写它,如果myErr导出实际异常,是否会发生位切片?
try {
mayThrowObjectDerivedFromMyErr();
} catch (myErr &err) {
err.append("Add to my message's base class here");
throw err; // Do I lose the derived class exception and only get myErr?
}
Run Code Online (Sandbox Code Playgroud) 寻找一些参考资料后弄明白,-unfortunately-我找不到任何关于理解之间的差异有用-和简单-描述throws
和rethrows
.当试图理解我们应该如何使用它时,这有点令人困惑.
我想提一下,我对-default-熟悉throws
传播错误的最简单形式,如下所示:
enum CustomError: Error {
case potato
case tomato
}
func throwCustomError(_ string: String) throws {
if string.lowercased().trimmingCharacters(in: .whitespaces) == "potato" {
throw CustomError.potato
}
if string.lowercased().trimmingCharacters(in: .whitespaces) == "tomato" {
throw CustomError.tomato
}
}
do {
try throwCustomError("potato")
} catch let error as CustomError {
switch error {
case .potato:
print("potatos catched") // potatos catched
case .tomato:
print("tomato catched")
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止一直很好,但问题出现在:
func throwCustomError(function:(String) throws -> ()) throws {
try function("throws string") …
Run Code Online (Sandbox Code Playgroud) 我用"throw;"重新抛出异常,但堆栈跟踪不正确:
static void Main(string[] args) {
try {
try {
throw new Exception("Test"); //Line 12
}
catch (Exception ex) {
throw; //Line 15
}
}
catch (Exception ex) {
System.Diagnostics.Debug.Write(ex.ToString());
}
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
正确的堆栈跟踪应该是:
Run Code Online (Sandbox Code Playgroud)System.Exception: Test at ConsoleApplication1.Program.Main(String[] args) in Program.cs:Line 12
但我得到:
Run Code Online (Sandbox Code Playgroud)System.Exception: Test at ConsoleApplication1.Program.Main(String[] args) in Program.cs:Line 15
但第15行是"抛出"的位置.我用.NET 3.5进行了测试.
我正在学习使用python.我刚刚看到这篇文章:http: //nedbatchelder.com/blog/200711/rethrowing_exceptions_in_python.html 它描述了在python中重新抛出异常,如下所示:
try:
do_something_dangerous()
except:
do_something_to_apologize()
raise
Run Code Online (Sandbox Code Playgroud)
因为你重新抛出异常,所以shouold是一个"外部catch-except"语句.但现在,我在想.如果except中的do_something_to_apologize()抛出错误怎么办?哪一个将被捕获在外部"捕获 - 除外"?你重新抛出的那个还是do_something_to_apologize()抛出的那个?或者首先捕获具有最高暴力的例外情况?
考虑以下C++代码:
try {
throw foo(1);
} catch (foo &err) {
throw bar(2);
} catch (bar &err) {
// Will throw of bar(2) be caught here?
}
Run Code Online (Sandbox Code Playgroud)
我希望答案是否定的,因为它不在try
块中,我在另一个问题中看到Java的答案是否定的,但是想确认C++也没有.是的,我可以运行一个测试程序,但是我想知道我的编译器有bug的远程情况下的行为的语言定义.
我认为抛出异常是一种很好的做法,让它冒泡回到用户界面或记录异常的地方并通知用户.
为什么resharper说这是多余的?
try
{
File.Open("FileNotFound.txt", FileMode.Open);
}
catch
{
throw;
}
Run Code Online (Sandbox Code Playgroud) 在我的onCreate()中,我设置了一个UncaughtException处理程序,如下所示:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
Log.e(getMethodName(2), "uncaughtException", throwable);
android.os.Process.killProcess(android.os.Process.myPid());
}
});
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我想恢复系统向用户显示强制关闭对话框的默认行为.
如果我尝试KillProcess()
用throw throwable
编译器替换调用,抱怨我需要用try/catch包围它.
如果我用try/catch包围它:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
try {
Log.e(getMethodName(2), "uncaughtException", throwable);
throw throwable;
}
catch (Exception e) {
}
finally {
}
}
});
Run Code Online (Sandbox Code Playgroud)
编译器仍然抱怨throw throwable
需要用try/catch包围.
我如何重新扔掉那个扔掉的?这样,除了信息量之外,Log.e()
系统的行为与以前完全一样:因为我从未设置默认的UncaughtException处理程序.
在网上引用了很多文档,尤其是关于SO的文档,例如:在C#中重新抛出异常的正确方法是什么? "扔e"之间应该有区别 和"扔".
但是,来自:http://bartdesmet.net/blogs/bart/archive/2006/03/12/3815.aspx,
这段代码:
using System;
class Ex
{
public static void Main()
{
//
// First test rethrowing the caught exception variable.
//
Console.WriteLine("First test");
try
{
ThrowWithVariable();
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
//
// Second test performing a blind rethrow.
//
Console.WriteLine("Second test");
try
{
ThrowWithoutVariable();
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
private static void BadGuy()
{
//
// Some nasty behavior.
//
throw new Exception();
}
private …
Run Code Online (Sandbox Code Playgroud) try {
// code which throws exception.
} catch (SQLException sqlex) {
logger.error("Custom message", sqlex);
**throw new CustomApplicationException("Custom message", sqlex);**
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,在粗体线上,我收到 PMD 错误,因为“catch 块中引发了新异常,原始堆栈跟踪可能会丢失”。我知道这个问题已经被问过很多次了,也有很多在线参考资料可供参考。我已经尝试了所有可能的方法。但我仍然无法消除这个 PMD 错误。请让我知道这段代码有什么问题。提前致谢!