当前位置:  开发笔记 > 编程语言 > 正文

捕获System.Exception等非特定异常是不好的做法?为什么?

如何解决《捕获System.Exception等非特定异常是不好的做法?为什么?》经验,为你挑选了3个好方法。

我目前正在进行代码审查,以下代码让我跳了起来.我看到这个代码存在多个问题.你是否同意我的观点?如果是这样,我如何向我的同事解释这是错误的(顽固型......)?

捕获一般异常(Exception ex)

使用"if(ex is something)"而不是另一个catch块

我们吃SoapException,HttpException和WebException.但是如果Web服务失败了,那就没那么多了.

码:

try
{
    // Call to a WebService
}
catch (Exception ex)
{
    if (ex is SoapException || ex is HttpException || ex is WebException)
    {
        // Log Error and eat it.
    }
    else
    {
        throw;
    }
}

Michael Hare.. 15

口头禅是:

如果能够正确处理异常,您应该只捕获异常

从而:

你不应该抓住一般例外.


在你的情况下,是的,你应该抓住那些例外并做一些有用的事情(可能不仅仅是吃它们 - 你可以throw在记录它们之后).

你的编码器正在使用throw(不是throw ex)哪个.

这是您可以捕获多个特定异常的方法:

try
{
    // Call to a WebService
}
catch (SoapException ex)
{
    // Log Error and eat it
}
catch (HttpException ex)
{
    // Log Error and eat it
}
catch (WebException ex)
{
    // Log Error and eat it
}

这几乎与您的代码相同.您的dev可能就是这样做的,以避免重复"日志错误并吃掉它"块.



1> Michael Hare..:

口头禅是:

如果能够正确处理异常,您应该只捕获异常

从而:

你不应该抓住一般例外.


在你的情况下,是的,你应该抓住那些例外并做一些有用的事情(可能不仅仅是吃它们 - 你可以throw在记录它们之后).

你的编码器正在使用throw(不是throw ex)哪个.

这是您可以捕获多个特定异常的方法:

try
{
    // Call to a WebService
}
catch (SoapException ex)
{
    // Log Error and eat it
}
catch (HttpException ex)
{
    // Log Error and eat it
}
catch (WebException ex)
{
    // Log Error and eat it
}

这几乎与您的代码相同.您的dev可能就是这样做的,以避免重复"日志错误并吃掉它"块.


一般来说,即使是"未知"的失败,正确的行为也不会停止并着火**.基本上,您不希望大型系统或应用程序因为意外发生而崩溃.IMO完全可以接受"顶级"处理程序来捕获所有内容并为应用程序/系统整体处理它.(批处理:报告该操作失败的结果可能没问题.UI:向用户报告错误(可能会记录/转发到某个地方开发人员可以查找,除非它真的是致命或数据完整性类型错误)

2> 小智..:

我目前正在进行代码审查,以下代码让我跳了起来.我看到这个代码存在多个问题.你是否同意我的观点?

不完全,见下文.

捕获一般异常(Exception ex)

一般来说,只要你重新抛出它(带有throw;),当你得出你无法处理它的结论时,捕获一般异常实际上是可以的.代码就是这样,所以这里没有直接的问题.

使用"if(ex is something)"而不是另一个catch块

catch块的净效果是实际上只处理SoapException,HttpException等,并且所有其他异常都在调用堆栈中传播.我想功能方面,这就是代码应该做的事情,所以这里也没有问题.

然而,从美学和可读性POV我更喜欢多个catch块到"if(ex是SoapException || ..)".一旦将公共处理代码重构为方法,多个catch块只会稍微打字,并且对于大多数开发人员来说更容易阅读.而且,最后一击很容易被忽视.

我们吃SoapException,HttpException和WebException.但是如果Web服务失败了,那就没那么多了.

这里可能潜伏着代码的最大问题,但是在不了解应用程序性质的情况下很难提供建议.如果Web服务调用正在执行您以后依赖的操作,那么仅记录和使用异常可能是错误的.通常,您将异常传播给调用者(通常在将其包装到例如XyzWebServiceDownException之后),甚至可能在重试webservice调用几次之后(在存在虚假网络问题时更加健壮).



3> Greg Beech..:

捕获和重新抛出相同异常的问题在于,虽然.NET尽最大努力保持堆栈跟踪完好无损,但它总是会被修改,这可能会导致跟踪故障实际来自更加困难的地方(例如异常)行号可能看起来是重新抛出语句的行而不是最初引发异常的行.有关捕获/重新抛出,过滤和未捕获之间差异的更多信息.

当存在像这样的重复逻辑时,你真正需要的是一个异常过滤器,所以你只能捕获你感兴趣的异常类型.VB.NET有这个功能,但不幸的是C#没有.假设的语法可能如下所示:

try
{
    // Call to a WebService
}
catch (Exception ex) if (ex is SoapException || ex is HttpException || /* etc. */)
{
    // Log Error and eat it
}

虽然你不能这样做,但我倾向于使用lambda表达式作为公共代码(你可以delegate在C#2.0中使用),例如

Action logAndEat = ex => 
    {  
        // Log Error and eat it
    };

try
{
    // Call to a WebService
}
catch (SoapException ex)
{
    logAndEat(ex);
}
catch (HttpException ex)
{
    logAndEat(ex);
}
catch (WebException ex)
{
    logAndEat(ex);
}


我很好奇为什么你使用lambda表达式而不是声明一个私有方法.也就是说,为什么"Action logAndEat"而不是"private void LogAndEat(Exception ex)"?
@Ben Robbins因为他可以:)当他只需要一个特定于该特定try-catch块的代码块时,他为什么要声明一个对整个类可见的方法?如果您在其他地方需要它,那么使用方法.就那么简单.
推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有