淺談 C# 語言的 using 語句

來源:互聯網
上載者:User
背景知識

外部排序指的是大檔案的排序,即待排序的記錄儲存在外儲存空間上,待排序的檔案無法一次裝入記憶體,需要在記憶體和外部儲存空間之間進行多次資料交換,以達到排序整個檔案的目的。外部排序最常用的演算法是多路歸併排序,即將原檔案分解成多個能夠一次性裝入記憶體的部分,分別把每一部分調入記憶體完成排序。然後,對已經排序的子檔案進行歸併排序。

問題提出

假設我們要寫一個外部排序程式。現在要討論的是對已經排序的子檔案進行歸併排序。

解決方案1

下面是外部排序歸併階段的程式碼片段:

01:  class ExternalSorting02:  {03:    void Merge(string inputFileName1, string inputFileName2, string outputFileName)04:    {05:      using (var reader1 = new StreamReader(inputFileName1))06:      {07:        using (var reader2 = new StreamReader(inputFileName2))08:        {09:          using (var writer = new StreamWriter(outputFileName))10:          {11:            Merge(reader1, reader2, writer);12:          }13:        }14:      }15:    }16:  17:    void Merge(TextReader reader1, TextReader reader2, TextWriter writer)18:    {19:      var s1 = reader1.ReadLine();20:      var s2 = reader2.ReadLine();21:      while (s1 != null || s2 != null)22:      {23:        if (Compare(s1, s2) <= 0) StepIt(ref s1, reader1, writer);24:        else StepIt(ref s2, reader2, writer);25:      }26:    }27:  28:    int Compare(string s1, string s2)29:    {30:      if (s1 == null && s2 == null) throw new ArgumentException("s1 和 s2 不能同時為 null");31:      if (s1 == null) return 1;32:      if (s2 == null) return -1;33:      return string.Compare(s1, s2);34:    }35:  36:    void StepIt(ref string s, TextReader reader, TextWriter writer)37:    {38:      writer.WriteLine(s);39:      s = reader.ReadLine();40:    }41:  }

上述代碼中的第 05 到 14 行的三個 using 語句逐個嵌套,依次縮排,是不是很難看?

注意,上述代碼中第 33 行可以替換為你想要的比較大小的方法,以便按照不同的關鍵字進行排序。

解決方案2

我們知道,可以將多個對象與 using 語句一起使用,但必須在 using 語句中聲明這些對象。因此,我們可以將上述的第 05 到 14 行的代碼重構如下:

1:  using (TextReader reader1 = new StreamReader(inputFileName1),2:                    reader2 = new StreamReader(inputFileName2))3:  {4:    using (TextWriter writer = new StreamWriter(outputFileName))5:    {6:      Merge(reader1, reader2, writer);7:    }8:  }

但是還是有兩個嵌套的 using 語句,不爽。

解決方案3

我們還知道,C# 編譯器實際上將 using 語句轉化為 try - finally 塊。那麼我們繼續進行重構:

01:  TextReader reader1 = null;02:  TextReader reader2 = null;03:  TextWriter writer = null;04:  try05:  {06:    reader1 = new StreamReader(inputFileName1);07:    reader2 = new StreamReader(inputFileName2);08:    writer = new StreamWriter(outputFileName);09:    Merge(reader1, reader2, writer);10:  }11:  finally12:  {13:    if (reader1 != null) reader1.Dispose();14:    if (reader2 != null) reader2.Dispose();15:    if (writer != null) writer.Dispose();16:  }

這樣看起來很不錯的樣子。注意:

  • 如果上述程式碼片段不是 Merge 方法中僅有的代碼塊,請使用一對大括弧將其括起來,以便為上述三個對象(reader1、reader2 和 writer)建立有限的範圍。
  • 實際上 C# 編譯器對解決方案1和解決方案2產生的 IL 代碼是差不多的,都是三個嵌套的 try - finally 塊。而不是象解決方案3中那樣只有一個 try - finally 塊。
解決方案4

我們知道 using 語句只不過是提供能確保正確使用 IDisposable 對象的方便文法。using 語句按照正確的方式調用對象上的 Dispose 方法,並會導致在調用 Dispose 時對象自身處於範圍之外。因此,可以重構如下:

1:  using (IDisposable reader1 = new StreamReader(inputFileName1),2:                     reader2 = new StreamReader(inputFileName2),3:                     writer = new StreamWriter(outputFileName))4:  {5:    Merge(reader1 as TextReader, reader2 as TextReader, writer as TextWriter);6:  }

這是我最喜歡的方案,你們呢?

解決方案5

但是,解決方案4中第 5 行中使用三個 as 進行強制類型轉換畢竟不爽。考慮進行以下重構:

1:  using (TextReader reader1 = new StreamReader(inputFileName1),2:         TextReader reader2 = new StreamReader(inputFileName2),3:         TextWriter writer = new StreamWriter(outputFileName))4:  {5:    Merge(reader1, reader2, writer);6:  }

可惜,上述程式碼片段無法通過編譯,出現以下編譯錯誤:

  CS1044: 在 for、using 和 fixed 或聲明語句中不能使用多個類型。

這個編譯錯誤實在是沒有道理。實際上在 for、using 和 fixed 語句中能夠使用多個類型對程式員來說很有用的,而且 C# 編譯器實現這點也沒有什麼困難。你們以為呢?

解決方案6

好吧,我們換一種方法進行重構:

1:  using (var reader1 = new StreamReader(inputFileName1),2:             reader2 = new StreamReader(inputFileName2),3:             writer = new StreamWriter(outputFileName))4:  {5:    Merge(reader1, reader2, writer);6:  }

非常遺憾,還是無法通過編譯。這次的錯誤資訊如下:

  CS0819: 隱式類型的局部變數不能有多個聲明符。

這個編譯錯誤也是沒有道理的。同樣,在隱式類型的局部變數中有多個聲明符對程式員來說也是很有用的,對 C# 編譯器來說也沒有什麼實現上困難。你們以為呢?

結論

建議修改 C# 編譯器,去掉 CS1044 和 CS0819 編譯錯誤,以便允許解決方案5和解決方案6,造福廣大 C# 程式員。

對於目前的 C# 編譯器,建議使用解決方案4。

 

參考資料
  1. using Statement (C# Reference)
  2. Wikipedia: External sotring
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.