• 异常


    异常

    • 异常是程序中的运行时错误,它违反了系统约束或应用程序约束,或出现了在正常操作时未预料的情形。
    class Program
        {
            static void Main(string[] args)
            {
                int x = 10, y = 0;
                x /= y;
                Console.ReadKey();
            }
        }
    //引发的异常:“System.DivideByZeroException”(位于_01WhatAbnormity.exe 中)
    //“System.DivideByZeroException”类型的未经处理的异常在_01WhatAbnormity.exe 中发生 尝试除以零。
    

    try语言

    • 用来指明为避免出现异常而被保护的代码段,并在发生异常时提供代码处理异常。

    • 3个部分组成:

      • 1.try块包含为避免出现异常而被保护的代码。
      • 2.catch子句部分含有一个或多个catch子句。这些事处理异常的代码段,它们也称为是异常处理程序。
      • 3.finally块含有在所有情况下都要被执行的代码,无论有没有异常发生。
    • 处理异常:把有可能导致异常的代码放在一个try块中,并提供一个简单的catch子句,以处理该异常。当异常发生时,它被捕获并在catch块中处理。

    class Program
        {
            static void Main(string[] args)
            {
                //int x = 10, y = 0;
                //x /= y;
                //Console.ReadKey();
    
                int x = 10;
                try
                {
                    int y = 0;
                    x /= y;//抛出一个异常
                }
                catch
                {
                    //处理异常的代码
                    Console.WriteLine("Handing all exception - Keep on Running");
                }
                Console.ReadKey();
                //输出:Handing all exception - Keep on Running
            }
        }
    

    异常类

    • 当一个异常发生时:
      • 1.创建该类型的异常对象;
      • 2.寻找适当的catch子句以处理它。
      • 3.所有的异常类都从根本上派生自System.Exception类
      • 4.异常对象含有只读属性,带有导致该异常的信息
    属性 类型 描述
    Message string 这个属性含有解释异常原因的消息。
    StackTrace string 这个属性含有描述异常发生在何处的信息
    InnerException Exception 如果当前异常是由另一个异常引起的,这个属性包含前一个异常的引用
    HelpLink string 这个属性可以被应用程序定义的异常设置,为异常原因信息提供URN或URL
    Source string 如果没有被应用程序定义的异常设定,那么这个属性含有异常所在的程序集的名称

    catch子句

    • catch子句处理异常的3种形式,允许不同级别的处理:
    //一般catch子句
    //1.在catch关键字之后没有参数列表
    //2.匹配try块中引起的任何类型的异常
    catch
    {
        Statements
    }
    //特定catch子句
    //1.带有异常类的名称作为单一参数
    //2.匹配任何该名称类型的异常
    catch(ExceptionType)
    {
        Statements
    }
    //带对象的特定catch子句
    //1.在异常类名称之后包括一个标识符
    //2.该标识符在catch子句块中相当于一个本地变量,被称为异常变量
    //3.异常变量引用异常对象,并能被用于访问关于该对象的信息。
    catch(ExceptionType ExceptionVariable)
    {
        Statements
    }
    
    • 一般catch子句能接受任何异常,但不能确定引发异常的类型。这只允许对任何可能发生的异常的普通处理和清理。
    • 特定catch子句形式把一个异常类的名称作为参数。它匹配该指定类或派生自它的异常类的异常。
    • 带对象的特定catch子句提供关于异常的最多信息。它匹配该指定类的异常,或派生自它的异常类的异常。它还给出一个异常实例(称为异常变量),是一个对CLR创建的异常对象的引用。可以在catch子句块内部访问异常变量的属性,以获取关于引起异常的详细信息。

    使用特定catch子句的示例

    此示例只处理DivideByZeroException类的异常。

    namespace _01WhatAbnormity
    {
        class Program
        {
            static void Main(string[] args)
            {
                //int x = 10, y = 0;
                //x /= y;
                //Console.ReadKey();
    
                int x = 10;
                try
                {
                    int y = 0;
                    x /= y;//抛出一个异常
                } 
                catch (DivideByZeroException e)
                {
                    Console.WriteLine("Message:{0}", e.Message);
                    Console.WriteLine("Source:{0}", e.Source);
                    Console.WriteLine("Stack:{0}", e.StackTrace);
                    //输出:
                    //Message:尝试除以零。
                    //Source: _01WhatAbnormity
                    //Stack:   在 _01WhatAbnormity.Program.Main(String[] args) 位置 F:C#C#Study1128.Abnormity1128.Abnormity\_01WhatAbnormityProgram.cs:行号 21
    
                }
                //catch (DivideByZeroException)
                //{
                //    Console.WriteLine("Handing an exception.");
                //    //输出:Handing an exception.
                //}
                catch
                {
                    //处理异常的代码
                    Console.WriteLine("Handing all exception - Keep on Running");
                    //输出:Handing all exception - Keep on Running
                }
                
                Console.ReadKey();
                
            }
        }
    }
    

    catch子句段

    • catch子句的目的是允许你以一种优雅的方式处理异常。
    • 若异常是由前一个异常引起的,则可以通过异常变量的InnerException属性来获得对前一个异常对象的引用。
    • catch子句段可以包含多个catch子句
    • 当异常发生时,系统按顺序搜索catch子句的列表,第一个匹配该异常对象类型的catch子句被执行。
    • catch子句的排序的两个重要规则
      • 特定catch子句必须以一种顺序排列,最明确的异常类型第一,直到最普通的类型
      • 若有一个一般catch子句,它必须是最后一个,并且在所有特定catch子句之后。

    finally块

    • 若程序的控制流进入了一个带finally块的try语句,那么finally始终会被执行。
    • 若在try块内部没有异常发生,则在try块的结尾,控制流跳过任何catch子句并到finally块。
    • 若在try块内部发生了异常,则在catch子句段中无论哪一个适当的catch子句被执行,接着就是finally块的执行。
    • 即使try块中有return语句或在catch块中抛出一个异常,finally块也总是会在返回到调用代码之前执行。

    为异常寻找处理程序

    • 若在try块内发生了异常,系统会查看是否有任何一个catch子句能处理该异常。
    • 若找到了适当的catch子句,以下3项中的1项会发生。
      • 该catch子句被执行。
      • 若有finally块,它被执行。
      • 执行在try语句的尾部继续。
    • 若异常在一个没有被try语句保护的代码中产生,或者try语句没有匹配的异常处理程序,系统将更进一步寻找匹配的处理代码。为此它会按顺序搜索调用栈,来查看是否存在带匹配的处理程序的封装try块。示例:
    namespace _02SearchCallStack
    {
        class Program
        {
            static void Main(string[] args)
            {
                MyClass myClass = new MyClass();
                try
                {
                    myClass.A();
                }
                catch(DivideByZeroException e)
                {
                    Console.WriteLine("catch clause in Main()");
                }
                finally
                {
                    Console.WriteLine("finally clause in Main()");
                }
                Console.WriteLine("After try statement in Main.");
                Console.WriteLine("---Keep running");
                Console.ReadKey();
                //输出:
                //finally clause in B()
                //finally clause in A()
                //catch clause in Main()
                //finally clause in Main()
                //After try statement in Main.
                //-- - Keep running
            }
        }
    
        class MyClass
        {
            public void A()
            {
                try
                {
                    B();
                }
                catch(System.NullReferenceException)
                {
                    Console.WriteLine("catch clause in A()");
                }
                finally
                {
                    Console.WriteLine("finally clause in A()");
                }
            }
    
            void B()
            {
                int x = 10, y = 0;
                try
                {
                    x /= y;
                }
                catch(System.IndexOutOfRangeException)
                {
                    Console.WriteLine("catch clause in B()");
                }
                finally
                {
                    Console.WriteLine("finally clause in B()");
                }
            }
        }
    }
    

    抛出异常

    • 使用throw语句使代码显式地引发一个异常。
    • throw语法:throw ExceptionObject;
    namespace _03ThrowException
    {
        class Program
        {
            static void Main(string[] args)
            {
                string s = null;
                MyClass.PrintArg(s);
                MyClass.PrintArg("Hi there!");
                Console.ReadKey();
                //输出:
                //Message: 值不能为 null。
                //参数名: arg
                //Hi there!
            }
        }
    
        class MyClass
        {
            public static void PrintArg(string arg)
            {
                try
                {
                    if(null == arg)
                    {
                        ArgumentNullException myEx = new ArgumentNullException("arg");//提供null参数的名称
                        throw myEx;
                    }
                    Console.WriteLine(arg);
                }
                catch(ArgumentNullException e)
                {
                    Console.WriteLine("Message:{0}", e.Message);
                }
            }
        }
    }
    

    不带异常对象的抛出

    • 在catch块内部,throw语句还可以不带异常对象使用
      • 这种形式重新抛出当前异常,系统继续它的搜索,为该异常寻找另外的处理代码。
      • 这种形式只能用在catch语句内部。
    • 示例:从第一个catch子句内部重新抛出异常:
    namespace _04ThrowWithNoException
    {
        class Program
        {
            static void Main(string[] args)
            {
                string s = null;
                MyClass.PrintArg(s);
                Console.ReadKey();
                //输出:
                //Inner Catch:值不能为 null。
                //参数名: arg
                //Outer Catch: Handing an Exception
            }
        }
        class MyClass
        {
            public static void PrintArg(string arg)
            {
                try
                {
                    try
                    {
                        if(null == arg)
                        {
                            ArgumentNullException myEx = new ArgumentNullException("arg");
                            throw myEx;
                        }
                        Console.WriteLine(arg);
                    }
                    catch(ArgumentNullException e)
                    {
                        Console.WriteLine("Inner Catch:{0}", e.Message);
                        throw;//重新抛出异常,没有附加参数
                    }
                }
                catch
                {
                    Console.WriteLine("Outer Catch: Handing an Exception");
                }
            }
        }
    }
    
  • 相关阅读:
    PSR
    php类与对象
    二进制、位运算及其用处
    安装LNMP笔记
    计算机基础
    Python3编写HFS(CVE2014-6287)检测脚本
    windows和iis对应版本关系
    phpStudy8.1.0.1配置子域名多网站
    Xml外部实体注入
    xss小游戏通关-全答案
  • 原文地址:https://www.cnblogs.com/ChaoJieLiu/p/11953486.html
Copyright © 2020-2023  润新知