程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C# 2.0:使用匿名方法、迭代程序和局部類來創建優雅的代碼(5)

C# 2.0:使用匿名方法、迭代程序和局部類來創建優雅的代碼(5)

編輯:關於C語言

迭代程序實現

編譯器生成 的嵌套類維持迭代狀態。當在 foreach 循環中(或在直接迭代代碼中)首次調用 迭代程序時,編譯器為 GetEnumerator 生成的代碼將創建一個帶有 reset 狀態 的新的迭代程序對象(嵌套類的一個實例)。在 foreach 每次循環調用迭代程序 的 MoveNext 方法時,它都從前一次 yield return 語句停止的地方開始執行。 只要 foreach 循環執行,迭代程序就會維持它的狀態。然而,迭代程序對象(以 及它的狀態)在多個 foreach 循環之間並不保持一致。因此,再次調用 foreach 是安全的,因為您將使新的迭代程序對象開始新的迭代。這就是為什麼 IEnumerable <ItemType> 沒有定義 Reset 方法的原因。

但是嵌套 迭代程序類是如何實現的呢?並且如何管理它的狀態呢?編譯器將一個標准方法 轉換成一個可以被多次調用的方法,此方法使用一個簡單的狀態機在前一個 yield return 語句之後恢復執行。您需要做的只是使用 yield return 語句指示 編譯器產生什麼以及何時產生。編譯器具有足夠的智能,它甚至能夠將多個 yIEld return 語句按照它們出現的順序連接起來:

public class CityCollection : IEnumerable<string>
{
  public IEnumerator<string> GetEnumerator()
  {
   yIEld return "New York";
   yIEld return "Paris";
   yIEld return "London";
  }
}

讓我們看一看在下面幾行代碼中顯示的該類的 GetEnumerator 方法:

public class MyCollection : IEnumerable<string>
{
  public IEnumerator<string> GetEnumerator()
  {
   //Some iteration code that uses yIEld return
  }
}

當編譯 器遇到這種帶有 yield return 語句的類成員時,它會插入一個名為 GetEnumerator$<random unique number>__IEnumeratorImpl 的嵌套類的 定義,如圖 5 中 C# 偽代碼所示。(記住,本文所討論的所有特征 — 編 譯器生成的類和字段的名稱 — 是會改變的,在某些情況下甚至會發生徹底 的變化。您不應該試圖使用反射來獲得這些實現細節並期望得到一致的結果。) 嵌套類實現了從類成員返回的相同 IEnumerable 接口。編譯器使用一個實例化的 嵌套類型來代替類成員中的代碼,將一個指向集合的引用賦給嵌套類的 <this> 成員變量,類似於圖 2 中所示的手動實現。實際上,該嵌套類是 一個提供了 IEnumerator 的實現的類。

Figure 5The Compiler- generated Iterator

public class MyCollection : IEnumerable<string>
{
  public virtual IEnumerator<string> GetEnumerator()
  {
    GetEnumerator$0003__IEnumeratorImpl impl;
   impl = new GetEnumerator$0003__IEnumeratorImpl;
   impl.<this> = this;
   return impl;
  }
  private class GetEnumerator$0003__IEnumeratorImpl :
    IEnumerator<string>
  {
   public MyCollection <this>; // Back reference to the collection
   string $_current;
   // state Machine members go here
    string IEnumerator<string>.Current
   {
     get
     {
      return $_current;
     }
   }
   bool IEnumerator<string>.MoveNext()
   {
     //State Machine management
   }
    IDisposable.Dispose()
   {
     //State Machine cleanup if required 
   }
  }
}

圖 5

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