• 异常处理


    异常处理

    在C#中,所有的异常都是使用一个异常类型的实例对象表示,都继承自System.Exception类型,或者直接使用System.Exception类型的实例对象;位于finally块中的代码可以保证不管代码是正常结束,还是进入异常处理代码块,其中的语句均会被执行,finally语句中放置资源回收的代码是一个不错的主意;BCL都提供了预定义的异常类供使用,其使用方式和应用级别的异常处理完全相同。

    异常类

    System.Exception类是所有异常类的基类,其中:

    • Message:只读字符串,此属性为当前的异常提供了描述性信息
    • InnerException:只读属性,值不为null,则可以通过它的值获取当前异常的异常实例;如果其值为null,则表示当前异常不是由其他异常引发的
    • StackTrace:只读字符串,描述了调用堆栈的内容,其中首先显示最近的方法调用

    为了区分系统级异常和应用级异常,BCL提供了两种直接继承自System.Exception的异常类型,System.SystemException和System.ApplicationException。因此我们编写的自定义异常应从ApplicationException继承。

    抛出异常

    public long Divide(int a, int b)
    {
        try
        {
            return a / b;
        }
        catch (System.DivideByZeroException e)
        {
            //抛出异常
            //如果有原始异常,推荐将原始异常传入
            throw new System.ArgumentException(“除数不能为0”, “b”, e);
        }
    }
    

    捕获异常

    处理异常时都按照从特定到最不特定(从具体到一般)的顺序对catch块中处理的异常进行排序,try/catch块有三种形式:try-catch、try-finally、try-catch-finally,不带catch或finally块的try语句将导致编译器错误。

    try {}  //可能引发异常的代码
    catch (System.ApplicationException e) {} //异常处理代码块,可以有多个
    catch (System.SystemException e) {}        //顺序从具体到一般
    finally {}  //不管是否发生异常,均会执行
    

    当异常发生后,CLR首先会判断当前引发的是何种异常类型,例如:是DivideByZeroException还是ArgumentException,然后以从上至下的顺序,搜索与当前执行语句(且和具体的异常类型)最匹配的catch块。搜索会从当前方法开始,寻找方法是否包括于一个try/catch块内,如果有,就对catch进行匹配,如果没有就定位到调用当前方法并继续寻找,一直向上层继续,直到找到为止。

    如果存在两个catch块,一个是捕获某个特定的异常,一个是捕获更加常规的异常,注意:

    • 捕获特定异常的匹配度要比捕获常规异常的匹配度高
    • 捕获特定类型的catch块和基类型的catch块同时存在,则前者要位于后者之前,否则无法通过编译
    class OneException : ApplicationException {}
    
    class Program
    {
        static void DoSomething()
        {
            throw new OneException();
        }
    
      static async Task Main(string[] args)
      {
        try
        {
            Program.DoSomething();
        }
        catch (OneException e)
        {
            //执行
            Console.WriteLine("OneException code");
        }
        catch (ApplicationException e)
        {
            //ApplicationException是OneException的基类,同时出现时必须放在它的后面,否则会编译错误
            Console.WriteLine("ApplicationException code");
        }
        catch (SystemException e)
        {
            Console.WriteLine("SystemException code");
        }
        finally
        {
            //执行
            Console.WriteLine("finally code");
        }
      }
    }
    

    一般来说,除非明确知道如何处理try块中可能引发的所有异常,或者catch块的末尾包括一条throw语句,否则请不要在catch块中指定Exception,

    自定义的异常

    自定义的异常应该从System.Application.Exception派生,创建时要注意:

    • 从System.Application.Exception和System.Exception派生
    • 使用Exception这个词作为自定义的异常名称为后缀
    • 至少提供三个公共构造函数(一个不包含参数的默认构造函数、一个可以包含异常消息的构造函数、一个可以包含异常消息,以及引发异常的异常引用的构造函数)

    异常处理方法

    • 尽量先由程序自动处理异常,若不能则考虑使用友好的提示告知用户,并根据等级记录日志
    • 限定异常范围,尽量缩小异常处理范围,如果只需要检测某一行代码,就不要把整段代码都放进try语句中
    • 应该尽量在上层捕获并处理异常(全局异常处理),过多的下层处理会有性能损失
  • 相关阅读:
    夏季适合IT程序员的养生小妙招
    夏季适合IT程序员的养生小妙招
    JS实现分钟数和时间小时 格式的转换
    Linux入门基础(1)
    Linux入门基础(1)
    Linux入门基础(1)
    常见通信协议HTTP、TCP、UDP的简单介绍
    BMP彩色转成黑色二值图
    《暗时间》笔记
    L53-Maximum-Subarray
  • 原文地址:https://www.cnblogs.com/home-wang/p/10972879.html
Copyright © 2020-2023  润新知