异常构造函数类

时间:2012-06-07 18:18:08

标签: c#

使用它时是否相同:

catch(Exception e)
{
    throw new Exception("some Exception", e);
}

和此:

catch(Exception e)
{
   throw new Exception("some Exception", e.InnerException);
}

或者我错过了什么?

3 个答案:

答案 0 :(得分:5)

在第二个示例中,您将丢弃已捕获的异常,而是使用其内部异常。您通常会在第一个示例中编写代码。

在第一种情况下,捕获的异常(e)成为您抛出的新异常的InnerException

catch(Exception e)
{
    throw new Exception("some Exception", e);
}

在第二种情况下,您使用InnerException的{​​{1}},e的数据丢失了:

e

答案 1 :(得分:3)

第一个例子一般来说更正确。当您因另一个异常而抛出一个新异常时,您应该将原始异常包含在新异常的内部异常中。

但这并非普遍适用。 可以在某些特定情况下非常有用,在这些情况下,您要撤消其他代码包含真实错误。

try {
  // some reflection call 
} catch (TargetInvocationException e) {
  // Reduce the layers of data a developer has to dig through by using the real
  // exception when I re-wrap
  throw new MyException("some message", e.InnerException);
}

答案 2 :(得分:2)

有三种方法可以重新抛出异常:

catch (Exception ex)
{
    throw;
}

抛出原始异常并保留原始堆栈跟踪。

catch (Exception ex)
{
    throw ex;
}

抛出原始异常,但原始堆栈跟踪丢失。堆栈跟踪现在将此行显示为异常的发起者。

catch (Exception ex)
{
    throw new Exception("...", ex);
}

引发新的异常,但保留原始异常及其堆栈跟踪作为新异常的InnerException

第一种情况非常有用,您需要清理失败但不成功。如果在两种情况下都需要清理,则使用finally子句,而不是catch子句。或者你只是想记录这里发生的异常并让调用者处理它。

第二种情况根本没用。你为什么要隐藏堆栈跟踪?可能有一些罕见的情况,这是有用的,但我不知道。

当您想要返回单一类型的异常(或类型系列)时,最常使用第三种情况。例如,您是一个文本解析方法,并且您希望将所有(非致命)异常转换为ParseException(或其他),这会提供其他详细信息,例如发生异常的文本中的行号。

在您提供的第二个示例中,捕获的异常将被完全丢弃。生成一个新异常,原始异常的InnerException成为此新异常的InnerException。我可以想象没有剥离中间异常会有用的情况。