• 异常的一些基础知识


    人们利用面向对象的机制描述异常类。在这个模型下,人们一般将异常分为如下几个类型。

    ·异常 (Exception)
    这是所有异常的基类,任何一个异常需要从此异常类继承并构造实例。

    ·系统异常 (SystemException)
    系统异常往往用来描述操作系统发生的异常。例如文件不存在,内存不足等。

    ·应用程序异常 (ApplicationException)
    在 SystemException 的托管(Managed)下,为不同俄进程引发应用程序异常。

    ·非法操作异常 (InvalidOperationException)
    此异常隶属于单个应用程序,当在某一个应用程序中发生非法操作(例如:空指针、Access Validation 等),应用程序可以在它自己的堆中托管这些异常。

    ·其他异常
    诸如被零除、格式转换、正则表达式、对象引用等异常,这些异常通常由编写这些应用程序的主语言自动捕获和处理。

    一般来说,异常都是按照如下形式继承和传递的。

      Exception
        -- SystemException
          -- ApplicationException
            -- InvalidOperationException
            -- UnhandledException
            -- IOException
              -- FileNotFoundException

    可见, 异常的发生也是由先后顺序的。捕获异常也是一样。异常总是被更下一层的类捕获,例如,如果同时在代码中捕获了 IOException 和 FileNotFoundException,那么可能将执行代码路径 2。

    try{
        System.IO.File.CreateText("c:\a.txt");
    }
    catch(IOException ex1)
    {……}   //path1
    catch(FileNotFoundException ex2)
    {……}   //path2
    finally
    {
    System.GC.Release;
    }
    这就要求在书写代码时正确的捕获异常

    异常的结构。在.NET Framework中,所有的异常派生自System.Exception基类。其下有两个子类:SystemException和ApplicationException。自行编写异常类,不建议直接派生自Exception类,而是应该派生自ApplicationException。

    Message:描述当前异常的消息
    Source:发生当前异常的方法/应用程序
    Stacktrace:和当前异常相关的堆栈追踪

    如果可能,为每个可能的Exception定制解决方法。将Exception基类放在最后一个Catch子句是一个好办法。
    如果不想让程序被错误所终止,要在适当的地方使用try-catch。如果想让异常处理继承,需要在catch子句中写出一些具体的处理方法,空的catch段相当于给异常放行。暗示,在进行完catch子句后程序将继承执行。除非catch子句中有return、throw、System.Environment.Exit()等。

    必须正确排列捕获异常的catch子句,范围小的Exception放在前面。可使用finally段来确保收尾工作。

    你无法预防异常,但你能处理它们,以避免它们使你的程序崩溃.

    当你的程序遇到一个非正常情况,比如说内存不足,它就会引发(throw/raise)一个异常.此时,当前的过程调用将挂起,.net运行时(CLR)将从下至上搜索过程调用堆栈,以查找相应的异常处理程序.也就是说如果抛出异常的代码正处于某个Try块中,运行时将首先使用本地的Catch块(如果有)来处理异常(它将执行在该位置找到的Catch块代码),否则这个程序段将被终止并将异常的处理权交给其调用函数;如果没有函数处理此异常(即在整个调用堆栈中没能找到适当的catch块),最终运行时将会得到并处理它,并立刻将你的程序终止.
    即使代码抛出异常,并在catch块中添加了显式的return语句,finally块中的代码仍会被执行.Finally块中的代码将在异常处理代码之后,控制返回到调用过程之前执行.使用break,continue,return语句退出finally块都是非法的。 

    Exception类是基本的.NET错误类。会存在一些具体的异常类,但是它们并不都来自Exception类。例如,处理具体的SQL错误。SqlClient类包括了SqlException对象以处理专门针对它的错误。可以加入另一个Catch块来处理针对SQL的错误

    创建自己的异常:

    ㈠声明一个异常,格式如下:class ExceptionName:Exception{}

    ㈡引发自己的异常:throw(ExceptionName);

    要避免使用了try-catch但没有处理异常的情况,否则就相当于给异常放行(这种情况还不如根本就不去捕获它)。
     处理完异常,我们还应该注意在finally块中释放相关资源、还原相关设置信息等收尾工作。
    在做异常处理的时候,最好能在应用程序所有的入口处(事件处理函数,主函数,线程入口)使用try-catch。 但是不要在程序构造函数入口处添加try-catch,因为此处产生异常,它自己并没有能力来处理,因为它还没有构造完毕,只能再向外层抛出异常。

    对于一些简单的、能够提前避免的错误,我们还是应该在try块外面及早做出处理。
    if(z == 0)
    {
    Console.WriteLine("除数不能为零");
    // ...
    }
    try
    {
    int x = y/z;
    }
    catch
    {
    // ...
    }

    将全局异常处理函数的委托加入到 Application.ThreadException 中,实现全局异常处理,但它只能处理主线程中未捕获的异常。在多线程异常处理时,工作线程/辅线程中产生异常,可以把它转给主线程来完成异常处理。如果线程之间不通知,是无法直接捕捉异常的。若没有去处理工作线程/辅线程中产生的异常,该异常将会“消失”掉。

    为什么要把异常处理都交给主线程去做呢?举个例子:在WinForm里我们使用多线程来处理界面元素,一旦有异常发生就将异常消息显示出来。那么,是直接在异常发生后就MessageBox,还是将消息交给MainUI来统一显示?试想一下,程序要是复杂点或是有多个界面采用多线程来显示界面元素,那么采用前者,我们就算知道了异常的详细信息,但可能还是很难找到究竟是哪里出了问题。而通过MainUI来显示,情况就要好很多了,尤其是还设计到其他东西的时候(如:多语言环境)。当然,这个例子只是很小的一个方面。


  • 相关阅读:
    redis中save和bgsave区别
    scrapy生成json中文为ASCII码解决
    mysql数据库,创建只读用户
    memcached命令行、Memcached数据导出和导入
    Memcache 查看列出所有key方法
    Elasticsearch5.x 引擎健康情况
    docker容器创建MariaDB镜像
    大文本数据排序
    换行符 和回车符
    索引与文本文件
  • 原文地址:https://www.cnblogs.com/flashicp/p/680130.html
Copyright © 2020-2023  润新知