程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#中的異常處理(二)

C#中的異常處理(二)

編輯:C#入門知識

三、finally?
 
  解決釋放問題的方法依靠你現在使用的語言。在C++中,你可以使用構建於堆棧上的析構函數。Java中,你能構使用finally程序塊。C#允許你創造自定義的結構類型但是不允許結構中的析構函數(只是因為一個C#析構函數其實是一個Finally方法,Finally被垃圾回收器調用。結構類,是一種值類型,並不歸屬於垃圾回收器回收的范圍)。因而,只是在開始,C#必須追循Java的道路,使用finally程序塊。首先,我們的finally程序塊開起來如下:
  private static char[] ReadSource(string filename)
  {
    try
    {
        FileInfo file = new FileInfo(filename);
        int length = (int)file.Length;
        char[] source = new char[length];
        TextReader reader = file.OpenText();
        reader.Read(source, 0, length);
    }
    finally
    {
        reader.Close();
    }
    return source;
  }

   這個版本不得不引入一個try程序塊(既然一個finally程序快必須跟隨在一個try程序塊後),這將是一個合理的解決方案,如果它奏效的話。但是,它沒有做到。問題是try程序塊構建成一個范圍,所以在finally程序塊中的reader並不在這個范圍內並且返回語句中的source也不在這個范圍。

  finally?

   為了解決這個問題,你不得不將reader和source的聲明移到try程序塊的外面,第二次嘗試如下:
  private static char[] ReadSource(string filename)
  {
    TextReader reader;
    char[] source;
    try
    {
        FileInfo file = new FileInfo(filename);
        int length = (int)file.Length;
        source = new char[length];
        reader = file.OpenText();
        reader.Read(source, 0, length);
    }
    finally
    {
        reader.Close();
    }
    return source;
  }

   這個版本將reader和source的聲明移到了try程序塊的外面,接著指派給reader和source但沒有初始化它們。這是和開始的“理想”版本不同的另外一個地方(出現兩個多余行)。然而,你可能認為如果它工作,那將是一個合理的解決方案。但是它沒有。問題是委派並不等同於初始化及讓編譯器知道它。如果在reader被分配之前出現一個異常,這是在finally程序塊中對reader.close()的調用
將根據沒有被分配的reader,C#,像Java一樣,不允許那樣。

  finally?

    很明顯,你必須要初始化reader,第三次嘗試如下:
  private static char[] ReadSource(string filename)
  {
    TextReader reader = null;
    char[] source;
    try
    {
        FileInfo file = new FileInfo(filename);
        int length = (int)file.Length;
        source = new char[length];
        reader = file.OpenText();
        reader.Read(source, 0, length);
    }
    finally
    {
        reader.Close();
    }
    return source;
  }

   這個版本引入了空值,這沒有出現在最初的“理想版本”中。不過,如果你仍然認為如果它起作用這將是一個合理的解決方式,然而它不是(雖然它能通過編譯)。問題是你在調用reader.close()的時候很容易拋出NullReferenceException異常。

  finally?

  一種解決方法是對eader.close()方法進行保護,下面做第四次嘗試:
  private static char[] ReadSource(string filename)
  {
    TextReader reader = null;
    char[] source;
    try
    {
        FileInfo file = new FileInfo(filename);
        int length = (int)file.Length;
        source = new char[length];
        reader = file.OpenText();
        reader.Read(source, 0, length);
    }
    finally


 

    {
        if (reader != null)
        {
            reader.Close();
        }
    }
    return source;
  }

   當然,對reader.close()的保護並不是ReadSource的理想版本。但是,如果僅從它的效果上看,這將是一個合理的版本。最終,工作。它和最初的版本已經大不相同。稍微努力,你能復用下面這段代碼:

  private static char[] ReadSource(string filename)
  {
    FileInfo file = new FileInfo(filename);
    int length = (int)file.Length;
    char[] source = new char[length];
    TextReader reader = file.OpenText();
    try
    {
        reader.Read(source, 0, length);
    }
    finally
    {
        if (reader != null)
        {
            reader.Close();
        }
    }
    return source;
  }

   在某些情況下,你可以在finally程序塊中對可能出現空值進行判斷(上面就是一個這樣的例子),但是一般說來,你最好還是在finally程序塊中判斷一下(考慮到如果file.OpenText返回空值,或者如果reader被放進了try程序塊中,或者reader作為ref/out參數被傳遞到try程序塊中)。你不得不增加一個try程序塊,一個finally程序塊,和一個if防護。如果你正在使用Java,你不得不每一次都去做這些事情。在那裡是個最大的問題。如果這個解決方案非常令人厭煩且完全偏離於最初的“完美”方案,這沒有關系,你能夠將這些異常提取到一塊。在Java中,你不能這麼做。遇到異常,Java將停止運行,而C#則將繼續。
 
  四、using語句
 
       在C#中,最接近於“理想”版本的是使用using語句:

  private static char[] ReadSource(string filename)
  {
    FileInfo file = new FileInfo(filename);
    int length = (int)file.Length;
    char[] source = new char[length];
    using (TextReader reader = file.OpenText())

    {
        reader.Read(source, 0, length);
    }
    return source;
  }

   Reader將會被恰當的關閉。簡單說來,using語句有大量的特征能夠改善開始的“理想”版本。首先,我們看一下它內在的運行機制到底是怎樣的。

  using語句轉換

    C#ECMA標准描述using聲明:
  using (type variable = initialization)
    embeddedStatement
  它等同於
  {
    type variable = initialization;
    try
    {
        embeddedStatement
    }
    finally
    {
        if (

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved