《随笔二十四》——C#中的 “ 异常 ”

目录

什么是异常

try 语句

System.Exceptin 异常类 (461P)

catch 子句

finally 块 (464P)

 使用 throw 语句 抛出一个异常 (469P)


什么是异常


异常是在运行期间代码中产生的错误。
 

int[] myArray = {1,2,3,4};     

int myEle = myArray[4];//数组下标越界 

运行到这里的时候,会出现异常,这个异常的定义已经在CLR中定义好了。如果我们不去处理这个异常,那么当异常发生的时候,程序会终止掉,然后异常后面的代码都无法执行。


try 语句


try 语句允许您指定要保护的代码块以防止出现异常,并在异常发生时提供处理异常的代码。

try 语句的结构

其中 catch 块可以有0或者多个,这里是处理异常的代码段,也被称为异常处理程序。

finally 可以有0或者1个。无论 try 块中是否抛出异常,此块都包含要执行的代码,即此块只要有,无论有没有发生异常,都会被执行。

namespace HelloWorld_Console
{

    class Program
    {
        static void Main(string[] args)
        {

            int x = 10;
            try
            {
                int y = 0;
                x /= y; // Raises an exception
            }
            catch // 如果 catch 块没有参数表,表示该块无论出现什么异常,都会被执行
            {

                WriteLine("Handling all exceptions - Keep on Running");
            }
            ReadKey();
        }
    }
}

System.Exceptin 异常类 (461P)


程序中可能会出现许多不同类型的异常。BCL定义了许多异常类,每个异常类代表一种特定的异常类型。 当其中一个发生时,CLR会执行以下操作:

  • 它为该类型创建异常对象。
  • 它寻找一个合适的 catch 子句来处理它。

所有异常类都派生自 System.Exceptin类, 下图显示了异常继承层次结构的一部分:

异常层次的结构

 

异常对象包含只读属性,其中包含导致异常的信息。下图显示了其中一些属性:

异常对象的选定属性

catch 子句


  catch  子句处理异常的形式有3种, 允许处理不同类型的异常。 如图所示:

catch子句的3种形式
  • 如图所示的第一种 catch子句能接受任何异常, 但不能确定导致它的异常类型。这只允许对任何可能发生的异常进行普通处理和清理。
  • 特定catch子句形式把一个异常类的名称作为参数。它匹配指定类的异常或从中派生的异常类的异常。
  • 带有对象的特定catch子句提供了关于异常的最多信息。它匹配指定类的异常或从中派生的异常类的异常。它通过将异常对象分配给异常变量,为您提供对CLR创建的异常对象的引用。您可以在catch子句的块中访问异常变量的属性,以获得关于引发的异常的特定信息。
namespace HelloWorld_Console
{
    class Program
    {
        static void Main(string[] args)
        {
       
            try
            {
                int[] myArray = { 1, 2, 3, 4 };

                int myEle = myArray[4];//数组下标越界 
            }
            catch(IndexOutOfRangeException e)
            { 
                Console.WriteLine("Message: {0}", e.Message); //输出发出异常的原因
                Console.WriteLine("Source: {0}", e.Source); // 输出发出哪个程序集发生了异常
                Console.WriteLine("Stack: {0}", e.StackTrace); // 这个程序集发出异常的具体位置
            }
        }
    }
}

如果你的 catch 子句接受一个参数, ,那么系统会把这个异常变量设置为异常对象, 这样你就可以检查并确定异常的原因。如果异常是前一个异常引起的, 你可以通过异常对象的 InnerException属性 来获得对前一个异常对象的引用

catch 子句部分可以包含多个catch子句,如图所示:

try语句中catch子句部分的结构

当异常发生时,系统按顺序搜索 catch 子句列表,并执行与异常对象类型匹配的第一个catch子句。因此,在对catch子句进行排序时,有两条重要的规则。它们如下:

  • 特定的catch子句必须先按最特定的异常类型排序,然后按最一般的顺序排序。
  • 如果有一个 一般 catch 子句,它必须是最后一个, 并且在所有特定catch子句之后。不鼓励使用一般catch子句, 因为它允许程序继续执行隐藏错误,让程序处于一种未知的状态。应尽可能使用特定catch子句。

finally 块 (464P)


  • 如果一个  try 语句带有 finally 块,那么  无论try 语句不不会发生异常, finally 语句都会被执行。
  • 注意: 如果只有 try 和 finally 块, 那么当在 try 中发生异常时, finally 块中的语句还是会执行, 但是在 finally 块之后的语句就不会被执行了。 最后的结果还是会抛出异常信息的。
  • 如果 当try 块中发生的异常, 如果有多个非一般的 catch 块,但是发生的异常类型并没有匹配到其中的任何一个, 那么(如果有的话)finally 就会被执行,但是在 finally 块之后的语句就不会被执行了。 最后的结果还是会抛出异常信息的。
  • 即使 try 块有一个 return 语句或者在 catch块中抛出了异常,finally块也将始终在返回调用代码之前执行。

namespace HelloWorld_Console
{
    class Program
    {
        static void Main(string[] args)
        {
            int inVal = 5;
            try
            {
                if (inVal < 10)
                {
                    Console.Write("First Branch - "); // 先执行这一语句
                    return;
                }
                else
                    Console.Write("Second Branch - ");
            }
            finally
            { Console.WriteLine("In finally statement"); } // 再执行这一语句
        }
    }
}

 使用 throw 语句 抛出一个异常 (469P)


可以使用 throw 语句显式地抛出一个异常,语法为:

throw ExceptionObject;
namespace HelloWorld_Console
{
    class MyClass
    {
        public static void PrintArg(string arg)
        {
            try
            {
                if (arg == null)
                {
                    ArgumentNullException myEx = new ArgumentNullException("arg");
                    throw myEx;
                }
                Console.WriteLine(arg);
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine("Message: {0}", e.Message);
            }
        }
    }
    class Program
    {
        static void Main()
        {
            string s = null;
            MyClass.PrintArg(s);
            MyClass.PrintArg("Hi there!");
        }
    }
}

输出结果为:
Message: Value cannot be null.
Parameter name: arg
Hi there!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值