C#迭代器

來源:互聯網
上載者:User

迭代器概述

迭代器是可以返回相同類型的值的有序序列的一段代碼。

迭代器可用作方法、運算子或 get 訪問器的代碼體。

迭代器代碼使用 yield return 語句依次返回每個元素。yield break 將終止迭代。有關更多資訊,請參見 yield。

可以在類中實現多個迭代器。每個迭代器都必須像任何類成員一樣有唯一的名稱,並且可以在 foreach 語句中被用戶端代碼調用,如下所示:foreach(int x in SampleClass.Iterator2){}

迭代器的傳回型別必須為 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。

迭代器是使用在foreach中的集合。在C#2.0中使用迭代器建立一個用於foreach的集合,實現上比較簡單:繼承於IEumnerable,並實現GetEnumerator()。

首先這個集合要基於IEnumerable(可以使用泛型),下面先來實現一個非泛型版的迭代器。代碼如下(非泛型程式碼範例來源於MSDN):

 

 public class DaysOfTheWeek : System.Collections.IEnumerable    {      string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };      public System.Collections.IEnumerator GetEnumerator()      {        for (int i = 0; i < m_Days.Length; i++)        {          yield return m_Days[i];        }      }    }    class TestDaysOfTheWeek    {      static void Main()      {        DaysOfTheWeek week = new DaysOfTheWeek();        foreach (string day in week)        {          System.Console.Write(day + " ");        }        Console.Read();      }   }

 

操作結果是:

Sun Mon Tue Wed Thr Fri Sat

其中yied return關鍵字產生枚舉元素

泛型版迭代器的實現代碼如下:

 

static void Main(string[] args)    {       Stack<int> stack = new Stack<int>();      stack.items = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };      foreach (int i in stack)      {        Console.WriteLine(i);      }      Console.Read();   }public class Stack<T> : IEnumerable<T>  {    public T[] items;    public IEnumerator<T> GetEnumerator()    {      for (int i = 0; i < items.Length; i++)      {        yield return items[i];      }    }    IEnumerator IEnumerable.GetEnumerator()    {      return GetEnumerator();    }}

 

運行結果如下:

1
2
3
4
5
6
7
8
9
10

其中G在實現泛型迭代器時我一直沒有寫IEnumerator IEnumerable.GetEnumerator()這個方法,所以編譯器一直在給我報錯,(猜想)這個方法應該IEnumerator<T>介面中的一個抽象方法。而這個方法中調用的GetEnumerator(),通過Integration Environment中的提示發現,實際上是上面寫到的IEnumerator<T> GetEnumerator()這個泛型方法。

在自訂迭代器時,我們可以利用yield break關鍵字跳出迴圈。如上面的例子中,我們想只輸出小於等於5的項,調整上面代碼,如:

 

public class Stack<T> : IEnumerable<T>
  {
    public T[] items;

    public IEnumerator<T> GetEnumerator()
    {

      for (int i = 0; i < items.Length; i++)
      {        

        if ((Convert.ToInt32(items[i]) > 5))
          yield break;

        yield return items[i];
      }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }
  }

 

 

操作結果:

 

1
2
3
4
5

 

迭代器的機制:

 

  實際上迭代器只是在C#2.0中通過編譯器一層額外處理的,用來簡化建立可用於foreach的枚舉集合的工作,從效能上沒有什麼變化。對於其產生的中繼語言沒有太多的變化。

執行個體:定義和使用命名迭代器

 

   class Class1
  {
    public IEnumerator GetEnumerator()
    {
      for (int i = 0; i < 10; i++)
      {
        yield return i;
      }
    }

 

    // 定義一個命名的迭代器,並可以提供參數
    public IEnumerable MaxToMin(int min, int max)
    {
      for (int i = max; i >= min; i--)
      {
        yield return i;
      }
    }

 

    // 定義一個迭代器類型的屬性,
    public IEnumerable MinToMax
    {
      // this表示該類執行個體,因為該類實現了GetEnumerator(),它是可枚舉的
      get { yield return this; }
    }

 

    public IEnumerable GetDescriptions()
    {
      yield return "this is my test";
      yield return "class name is class1";
      yield return "ktgu";
    }
  }

 

  static void Main(string[] args)
  {
    
    Class1 c = new Class1();

 

    foreach (int i in c)
    {
      Console.WriteLine(i);
    }

 

    foreach (int i in c.MaxToMin(1, 10))
    {
      Console.WriteLine(i);
    }

 

    foreach (int i in c.MinToMax)
    {
      Console.WriteLine(i);
    }

 

    foreach (string s in c.GetDescriptions())
    {
      Console.WriteLine(s);
    }
   }

 

迭代效果及實現要點

 

1.迭代抽象:訪問一個彙總對象的內容而無需暴露它的內部表示。

 

2.迭代多態:為遍曆不同的集合結構提供一個統一的介面,從而支援同樣的演算法在不同的集合結構上進行操作。

 

3.迭代器的健壯性考慮:遍曆的同時更改迭代器所在的集合結構,會導致問題。

 

適用性

 

1.訪問一個彙總對象的內容而無需暴露它的內部表示。

 

2.支援對彙總對象的多種遍曆。

 

3.為遍曆不同的彙總結構提供一個統一的介面(即, 支援多態迭代)。

 

總結

 

Iterator模式就是分離了集合對象的遍曆行為,抽象出一個迭代器類來負責,這樣既可以做到不暴露集合的內部結構,又可讓外部代碼透明的訪問集合內部的資料

參考:
C#2.0-迭代器應用 http://cs.alienwave.cn/Topic/1347.aspx
迭代器(C# 編程指南) http://msdn2.microsoft.com/zh-cn/library/dscyy5s0(VS.80).aspx

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.