zoukankan      html  css  js  c++  java
  • 异常处理详解

    如何处理异常

           作为一个开发人员,你应该感受到通过try, catch, finally块来构建一个结构化异常处理机制的优点。.NET框架提供了一大堆异常处理层次来处理不同种类的异常。所有的异常都继承自Exception(基类)。你可以通过继承来实现自定义错误处理以扩展异常处理机制。不幸的是,很多开发人员都误用了这种架构能力。一个随时要记着的事是当一个异常发生在运行时时(这个架构)应该如何运作?一般有以下三种情况:

    1. 忽略异常,让它在调用栈里上升而被其它的catch块捕获。
    2. 捕获异常,同时为你的应用程序执行必要的动作,如果你不想再次在异常中抛出异常的话。
    3. 捕获异常,并用其它异常覆盖它。这样和你的应用程序有更密切的关系。异常覆盖是为了避免打破(架构中的)抽象层次。你可以通过你抛出的异常的 InnerException属性指定原异常是什么,这样就可以把你现有的异常用一个新的异常来覆盖了(更与你系统有关的)。为了了解异常覆盖,让我们来看一个能引起IOException异常的方法,你可以在应用级别使用LoadingException 或 FailtoLoadInfoException来覆盖原有的IOException异常,这样比把底层的IOException给用户看到要来的好些。

    一个应用程序的异常处理框架应该有以下几种(要求):

    • 探测异常;
    • 执行代码清除;
    • 内部异常覆盖;
    • 内部异常替换;
    • 记录并报告错误信息;
    • 建立能被外部监视的事件以帮助系统操作;

    在开始你应该建立一个一致的,健壮的异常管理架构,在你所有的系统中应该很好的封装并抽象其记录和报告等的细节。

    好的习惯

           以下列出一些不错的提示/建议供你在(设计)异常处理(时)参考:

    • 抛出异常要不小的代价。所以,你应该尽可能地在“异常情况”下进行异常处理,不要去控制正规逻辑流程。比如,以下代码:
    void EmpExits(string EmpId)
    {
        
    // search for employee
        if(dr.Read(EmpId) == 0// no record found
        {
            
    throw(new Exception("Emp Not found"));
        }
    }

    应该用以下代码:
    bool EmpExits(string EmpId)
    {
        
    // search for employee
        if(dr.Read(EmpId) == 0// no record found
        {
            
    return false;
        }
    }

    • 避免在循环中捕获异常,如果实在是要捕获,那把整个循环都放在try/catch块里。
    • 采用标准try/catch/finally异常处理方式进行处理,这在托管代码里是被推荐的。最后的Finally块确保异常事件中的资源都被释放掉了。
      比如:
    SqlConnection conn = new SqlConnection("");
    try
    {
        conn.Open();
        
    // some operation
        
    // some additional operations
    }
    catch (Exception ex)
    {
        
    // handle the exception
    }
    finally
    {
        
    if (conn != null && conn.State == ConnectionState.Open)
            conn.Close(); 
    // closing the connection
    }

    • 尽可能的用校验代码而避免使用异常。如果你知道一个可避免的条件可能会出现,那就让它避免。比如,在执行任何操作以前,检查空值(VB里是Nothing),这样可以避免使用异常以及性能问题。
      以下代码:
    double result = 0;
    try
    {
        result 
    = firstVal/secondVal;
    }
    catch(System.Exception e)
    {
        
    // handling the zero divided exception
    }

    应该替换成:
    double result = 0;
    if(secondVal != null && secondVal > 0)
    {
        result 
    = firstVal/secondVal;
    }
    else
    {
        result 
    = System.Double.NaN;
    }

    • 不要为没有必要的情况(原文:reasons)抛出异常。再次抛出异常的开销和实例化一个新异常的开销一样的大,同时再次抛出异常使程序调试工作增加难度。比如:
    try
    {
        
    // Perform some operations ,in case of  throw an exception…
    }
    catch  (Exception e)
    {
        
    // Try to handle the exception with e
        throw;
    }

    • 推荐的处理不同的错误的不同的方法是实现一系列的catch块,这看起来好像没有什么,但可以让你的异常处理从特殊走向普通。比如捕获一个和文件有关的异常明显要比捕获一个FileNotFoundException, DirectoryNotFoundException, SecurityException, IOException, UnauthorizedAccessException甚至最后的基类Exception,好的多。
    • ADO.NET 的错误应该通过 SqlException 或 OleDbException来处理。
    • 使用ConnectionState属性来检查连接是否可用要比异常处理好的多。
    • 要常使用Try/Finally,Finally提供了关闭连接的机会。Using语句可以达到同样的效果。
    •         用指定的处理程序来处理异常。在一些情况下如果你知道一些可能的异常那就用相应的异常处理类,比如:
    try
    {
        
    }
    catch(SqlException sqlexp)  // specific exception handler
    {
        
    }
    catch(Exception ex) // Generic exception handler
    {

    }

    • 你的异常处理架构应该可以探测异常并在内部将其覆盖,(或是)使用其它异常将其替换,或是为监视系统而记录和报告这些信息。
    • 推荐大家使用 Microsoft's patterns & practices 团队 提供的 Exception Management Application Block。这是一个简单且可扩展的框架用于记录异常信息到事件文件中,你可以自定义它,把日志记录到其它数据源中同时不影响你系统的代码。Exception Management Application Block都是一些由patterns & practices团队开发的很好的代码,并且已经彻底地被Microsoft labs给测试过了。
  • 相关阅读:
    [ZJOI2007]仓库建设(斜率dp优化)
    [HNOI2008]玩具装箱toy(斜率优化dp)
    2019牛客暑期多校训练营(第十场)F-Popping Balloons
    2019牛客暑期多校训练营(第十场)B-Coffee Chicken
    子集的生成—二进制枚举
    2019牛客暑期多校训练营(第九场)D-Knapsack Cryptosystem(思维+子集和)
    2019牛客暑期多校训练营(第九场) E-All men are brothers(并查集+组合数学)
    字符串的最小表示法
    2019牛客暑期多校训练营(第八场)
    [HDU4734] 不要62(数位dp入门)
  • 原文地址:https://www.cnblogs.com/ejiyuan/p/568146.html
Copyright © 2011-2022 走看看