深层次详解Exception

在Ilustrustor C# 2008中这样描述Exception:The BCL defines a number of exception classes,each representing a specific type.When one occurs,the CLR

  • Create an exception object for the type
  • Looks for an appropriate catch clause to handle it

所有的异常类都继承自System.Exception类,当异常产生时,CLR将创建该异常类的实例对象,将从最底层依次寻找合适的异常类型,同时若存在catch语句时将会选择最合适的语句进行处理。

 catch语句包括三种形式:

?View Code CSHARP
/*第一种:通用型*/
catch
{
   //Statements
}
/*第二种:特殊类型*/
catch(ExceptionType)
{
   //Statements
}
/*第三种:带对象的特殊类型*/
catch(ExceptionType InstanceID)
{
   //Statements
}

若使用第三种类型,可以得到异常实例 InstanceID的相关属性,如Message、Source等。

多catch的处理原则

一个异常发生时,会跳转到与异常异常最匹配的catch块执行,继承链决定了匹配度。

?View Code CSHARP
/// <summary>
/// 选择处理异常类
/// </summary>
public static void HandleExceptionMethod()
{
    try
    {
        throw new ApplicationException("ApplicationException Occur!");
    }
    catch (NullReferenceException)
    {
        //Handle1
        Console.WriteLine("Handle1");
    }
    catch (ArgumentException)
    {
        //Handle2
        Console.WriteLine("Handle2");
    }
    catch (ApplicationException)
    {
        //Handle3
        Console.WriteLine("Handle3");
    }
    catch (SystemException)
    {
        //Handle4
        Console.WriteLine("Handle4");
    }
    catch (Exception)
    {
        //Handle5
        Console.WriteLine("Handle5");
    }
    Console.ReadKey();
}

运行结果

在上例中共有5个catch块,注意catch块必须按照从最具体到最常规的顺序排列,否则可能造成编译错误。例若将Handle5的向上移到Handle4前面,则发生编译错误

关于throw

在上例中我们实际上已经使用了throw来手工抛出异常,在C#中发生异常时隐含CLR会throw(引发)异常。这句话里我们注意到都是使用throw。因此在实际应用中throw常用于重新引发已捕获的异常及显式引发异常,比如上例中就是显式引发异常。

?View Code CSHARP
/// <summary>
/// throw
/// </summary>
public class ThrowDemo
{
    public static void ThrowDemoMethod()
    {
        FileStream fs = null;
        try
        {
            fs = new FileStream("c:\\data.txt";, FileMode.Open);//该文件并不存在
            StreamReader sr = new StreamReader(fs, System.Text.Encoding.Default, false);
            string line;
            //A value is read from the file and output to the console.
            line = sr.ReadLine();
            Console.WriteLine(line);
        }
        catch (FileNotFoundException)
        {
            throw new FileNotFoundException("data.txt is not existed");
        }
        finally
        {
            fs.Close();
        }
    }
}

编译器在编译时,将会产生一个FileNotFoundException,进入catch处理,catch语句中重新触发了此异常,并提示“data.txt is not existed"。执行结果如图

注意异常中的提示文字并不相同:第二次是系统异常的提示文字。

本节源码下载

另附 Exception层次图(原图见http://book.javanb.com/From-Java-To-Csharp-A-Developers-Guide/0321136225_ch13lev1sec2.html)

Related posts:

  1. C#难点逐个击破(10):is与as is C#中允许数据在继承链中向下转型,在转换前需要判断数据的类型,可以使用is来判断基础类型。可以这样来理解:若该对象可以非空,且可以强制转换为所提供的类型而不引发异常,则is表达式返回true。使用语法为: if(obj is objType) { } 若obj为null则返回false; /// <summary>...
  2. C#难点逐个击破(12):new 使用new重写基类成员 继承类不能删除基类中的成员,但可以使用new关键字来隐藏基类的该成员;new关键字可以显式隐藏从基类继承的成员;若不使用new关键字直接声明同名成员则会出现警告,例: ?View Code CSHARPclass BaseClass { protected int age...
  3. C#难点逐个击破(11):分部类(partial class) 分部类 分部类是一个类的多个部分,可以认为是其子集,所有分部类可以合并成一个完整的类; 可以在一个文件或多个文件中定义分部类 值得注意的是,修饰符partial并不是C#关键字,因此在上下文中可以使用partial作为标识符,但如果是在关键字class、struct或interface中,它就代表分部类。 file1.cs       partial class MyPartClass...
  4. C#难点逐个击破(1):ref参数传递 c#...

以上关联文章由 Yet Another Related Posts Plugin 提供支持。