当前位置:  开发笔记 > 数据库 > 正文

为什么要重新抛出异常?

如何解决《为什么要重新抛出异常?》经验,为你挑选了4个好方法。

我多次看过以下代码:

try
{
    ... // some code
}
catch (Exception ex)
{
    ... // Do something
    throw new CustomException(ex);

    // or
    // throw;

    // or
    // throw ex;
}

你能解释重新抛出异常的目的吗?它是否遵循异常处理中的模式/最佳实践?(我在某处读过它被称为"来电通知"模式?)



1> Chris Jester..:

如果您想要记录异常但不处理异常,则重新抛出相同的异常非常有用.

抛出一个包装被捕获异常的新异常有利于抽象.例如,您的库使用第三方库,该库会引发您的库的客户端不应该知道的异常.在这种情况下,您将它包装到一个更原生于您的库的异常类型中,然后抛出它.


我的意思是:如果你有一段代码无法处理异常(即你希望你的调用者处理它),你有两个选择:1.不要抓住它; 抓住它,将它记录在某个地方,然后重新抛出它.通过重新抛出,呼叫者看起来好像从未被捕获过.

2> Davy Landman..:

实际上有区别

throw new CustomException(ex);

throw;

第二个将保留堆栈信息.

但有时您希望使Exception对您的应用程序域更加"友好",而不是让DatabaseException到达您的GUI,您将引发包含原始异常的自定义异常.

例如:

try
{

}
catch (SqlException ex)
{
    switch  (ex.Number) {
        case 17:
        case 4060:
        case 18456:
           throw new InvalidDatabaseConnectionException("The database does not exists or cannot be reached using the supplied connection settings.", ex);
        case 547:
            throw new CouldNotDeleteException("There is a another object still using this object, therefore it cannot be deleted.", ex);
        default:
            throw new UnexpectedDatabaseErrorException("There was an unexpected error from the database.", ex);
    } 
}


你的第一个陈述是误导性的.抛出新的CustomException(ex)不会导致您丢失堆栈信息,它将保留在CustomException对象的InnerException中.这是你扔前的时候; 堆栈丢失了.

3> RoadWarrior..:

有时您希望隐藏方法的实现细节或提高问题的抽象级别,以便它对方法的调用者更有意义.为此,您可以拦截原始异常并替换更适合解释问题的自定义异常.

例如,从文本文件加载所请求用户的详细信息的方法.该方法假定存在一个以用户ID和后缀".data"命名的文本文件.当该文件实际上不存在时,抛出FileNotFoundException没有多大意义,因为每个用户的详细信息存储在文本文件中的事实是该方法内部的实现细节.因此,此方法可以使用解释性消息将原始异常包装在自定义异常中.

与您显示的代码不同,最佳实践是应通过将其作为新异常的InnerException属性加载来保留原始异常.这意味着开发人员仍然可以在必要时分析底层问题.

当您创建自定义异常时,这是一个有用的清单:

•找到一个好名称,它表示抛出异常的原因,并确保名称以"Exception"结尾.

•确保实现三个标准异常构造函数.

•确保使用Serializable属性标记例外.

•确保实现反序列化构造函数.

•添加任何可帮助开发人员更好地理解和处理异常的自定义异常属性.

•如果添加任何自定义属性,请确保实现并覆盖GetObjectData以序列化自定义属性.

•如果添加任何自定义属性,请覆盖Message属性,以便将属性添加到标准异常消息中.

•请记住使用自定义异常的InnerException属性附加原始异常.



4> Greg Beech..:

您通常会因为以下两个原因之一而捕获并重新抛出,具体取决于代码在应用程序中的架构位置.

在应用程序的核心,您通常会捕获并重新抛出异常,将异常转换为更有意义的异常.例如,如果您正在编写数据访问层并使用SQL Server自定义错误代码,则可能会将SqlException转换为ObjectNotFoundException之类的内容.这很有用,因为(a)它使调用者更容易处理特定类型的异常,并且(b)因为它阻止了该层的实现细节,例如你使用SQL Server将持久性泄漏到其他层的事实,允许您更轻松地更改未来的事物.

在应用程序的边界,通常在不转换异常的情况下捕获和重新抛出异常,以便您可以记录它的详细信息,帮助调试和诊断实时问题.理想情况下,您希望在操作团队可以轻松监视的某个位置(例如,事件日志)发布错误,以及在开发人员的控制流中发生异常的位置(通常是跟踪).

推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有