什么是迭代器,創(chuàng)建并使用迭代器.為整數(shù)列表創(chuàng)建迭代器.為泛型列表創(chuàng)建迭代器 收藏
迭代器
導(dǎo)讀
什么是迭代器
創(chuàng)建并使用迭代器
為整數(shù)列表創(chuàng)建迭代器
為泛型列表創(chuàng)建迭代器
什么是迭代器
迭代器(iterator)
迭代器是一種方法、get 訪問器或運算符,它通過使用 yield 關(guān)鍵字對數(shù)組或集合類執(zhí)行自定義迭代。yield 返回語句會導(dǎo)致源序列中的元素在訪問源序列中的下一個元素之前立即返回給調(diào)用方。盡管您以方法的形式編寫迭代器,但編譯器會將其轉(zhuǎn)換為一個實際上是狀態(tài)機的嵌套類。只要客戶端代碼中的 foreach 循環(huán)繼續(xù)進行,此類就會跟蹤迭代器的位置。
注意:
若要了解編譯器在后臺執(zhí)行了什么操作,請使用 ILDASM.exe 工具來查看為迭代器方法生成的中間語言 (IL) 代碼。
將使用 foreach 語句從客戶端代碼中調(diào)用迭代器。例如,您可以為類創(chuàng)建一個迭代器,該迭代器將按相反順序返回元素,或在迭代器返回元素之前對每個元素執(zhí)行操作。在為類或結(jié)構(gòu)創(chuàng)建迭代器時,您不必實現(xiàn)整個 IEnumerator 接口。當(dāng)編譯器檢測到迭代器時,它將自動生成 IEnumerator 或 IEnumerator<(Of <(T>)>) 接口的 Current、MoveNext 和 Dispose 方法。
迭代器概述
l 迭代器是可以返回相同類型的值的有序序列的一段代碼。
l 迭代器可用作方法、運算符或 get 訪問器的代碼體。
l 迭代器代碼使用 yield return 語句依次返回每個元素。yield break 將終止迭代。
l 可以在類中實現(xiàn)多個迭代器。每個迭代器都必須像任何類成員一樣有唯一的名稱,并且可以在 foreach 語句中被客戶端代碼調(diào)用,如下所示:foreach(int x in SampleClass.Iterator2){}。
l 迭代器的返回類型必須為 IEnumerable、IEnumerator、IEnumerable<(Of <(T>)>) 或 IEnumerator<(Of <(T>)>)。
l 迭代器是 LINQ 查詢中延遲執(zhí)行行為的基礎(chǔ)。
yield 關(guān)鍵字用于指定返回的一個或多個值。到達 yield return 語句時,會保存當(dāng)前位置。下次調(diào)用迭代器時將從此位置重新開始執(zhí)行。
迭代器對集合類特別有用,它提供一種簡單的方法來迭代復(fù)雜的數(shù)據(jù)結(jié)構(gòu)(如二進制樹)。
示例
在本示例中,DaysOfTheWeek 類是將一周中的各天作為字符串進行存儲的簡單集合類。foreach 循環(huán)每迭代一次,都返回集合中的下一個字符串
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//導(dǎo)入命名空間
using System.Collections;
namespace MvcUsedKeywords
{
public class DaysOfTheWeek:IEnumerable
{
string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
//實現(xiàn)接口中的方法,創(chuàng)建迭代器
public IEnumerator GetEnumerator()
{
for (int i = 0; i < m_Days.Length; i++)
{
yield return m_Days[i];
}
}
}
class TestDaysOfTheWeek
{
static void Main(string[] args)
{
DaysOfTheWeek week = new DaysOfTheWeek();
foreach (string day in week)
{
Console.Write(day + " ");
}
Console.WriteLine();
}
}
}
調(diào)試下發(fā)現(xiàn),foreach中每調(diào)用一次week,GetEnumerator()方法中的for循環(huán)一次,感覺是在同步進行。
運行結(jié)果: Sun Mon Tue Wed Thr Fri Sat
創(chuàng)建并使用迭代器
創(chuàng)建迭代器最常用的方法是對 IEnumerable 接口實現(xiàn) GetEnumerator 方法。GetEnumerator 方法的存在使得類型成為可枚舉的類型,并允許使用 foreach 語句。foreach 語句調(diào)用類中實現(xiàn)GetEnumerator()方法,并使用返回的枚舉數(shù)來循環(huán)訪問值。如下例中的創(chuàng)建迭代器1,創(chuàng)建迭代器2。
還可以使用命名的迭代器以支持通過不同的方式循環(huán)訪問同一數(shù)據(jù)集合。例如,您可以提供一個按升序返回元素的迭代器,而提供按降序返回元素的另一個迭代器。迭代器還可以帶有參數(shù),以便允許客戶端控制全部或部分迭代行為。如下例中的創(chuàng)建迭代器3。
可以在同一個迭代器中使用多個 yield 語句。如下例中的創(chuàng)建迭代器4。
為泛型列表創(chuàng)建迭代器塊,要實現(xiàn)泛型接口 IEnumerator<T>),還要實現(xiàn)非泛型 GetEnumerator,因為 IEnumerable<T>) 繼承自 IEnumerable。如下例中的創(chuàng)建迭代器5。在類名后加個類型<T>,類里聲明了一個類型 T 的數(shù)組,并使用 Add 方法給數(shù)組賦值。在 GetEnumerator 方法中,使用 yield return 語句返回數(shù)組的值。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//導(dǎo)入命名空間
using System.Collections;
namespace MvcUsedKeywords
{
//創(chuàng)建迭代器1
class ListOne
{
//實現(xiàn)接口IEnumerable里的GetEnumerator()方法
public IEnumerator GetEnumerator()
{
for (int i = 0; i < 10; i++)
{
yield return i;
}
}
}
//創(chuàng)建迭代器2
class ListTwo : IEnumerable
{
//實現(xiàn)接口IEnumerable里的GetEnumerator()方法
public IEnumerator GetEnumerator()
{
for (int i = 0; i < 10; i++)
{
yield return i;
}
}
}
//創(chuàng)建迭代器3
class ListThree
{
//使用命名的迭代器來定義,返回0-9的偶數(shù)
public IEnumerable GetEvenNumber()
{
for (int i = 0; i < 10; i = i + 2)
{
yield return i;
}
}
//使用命名的迭代器來定義,返回指定范圍里的偶數(shù)
public IEnumerable GetEvenNumber(int start, int end)
{
for (int i = start; i <= end; i++)
{
yield return i;
}
}
}
//創(chuàng)建迭代器4
class ListFour
{
//可以在同一個迭代器中使用多個 yield 語句
public IEnumerator GetEnumerator()
{
yield return "我是";
yield return "中國人,";
yield return "我愛編程.";
yield return "你呢?";
}
}
class ListClass
{
static void Main(string[] args)
{
//利用實現(xiàn)接口IEnumerable里的GetEnumerator()方法
Console.Write("方式一:");
ListOne list1 = new ListOne();
foreach (int i in list1)
{
Console.Write(i + " ");
}
//利用實現(xiàn)接口IEnumerable里的GetEnumerator()方法
Console.Write("\n方式二:");
ListTwo list2 = new ListTwo();
foreach (int i in list2)
{
Console.Write(i + " ");
}
//調(diào)用命名的迭代器,無參數(shù)。返回0-9的偶數(shù)
Console.Write("\n調(diào)用命名的迭代器:");
ListThree list3 = new ListThree();
foreach (int i in list3.GetEvenNumber())
{
Console.Write(i+" ");
}
//調(diào)用命名的迭代器,有參數(shù)。返回指定范圍里的偶數(shù)
Console.Write("\n調(diào)用命名的迭代器:");
foreach (int i in list3.GetEvenNumber(10, 20))
{
Console.Write(i + " ");
}
//調(diào)用用多個yield語句的迭代器
ListFour list4 = new ListFour();
Console.Write("\n用多個yield語句:");
foreach (string i in list4)
{
Console.Write(i);
}
}
}
}
輸出:
方式一:0 1 2 3 4 5 6 7 8 9
方式二:0 1 2 3 4 5 6 7 8 9
調(diào)用命名的迭代器:0 2 4 6 8
調(diào)用命名的迭代器:10 11 12 13 14 15 16 17 18 19 20
用多個yield語句:我是中國人,我愛編程.你呢?
為整數(shù)列表創(chuàng)建迭代器
使用一個整數(shù)數(shù)組來構(gòu)建列表。for 循環(huán)對集合進行循環(huán)訪問,并返回每項的值。然后使用 foreach 循環(huán)來顯示該集合的項。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//導(dǎo)入命名空間
using System.Collections;
namespace MvcUsedKeywords
{
//為整數(shù)列表創(chuàng)建迭代器塊
public class ListNum
{
public int[] items;
public ListNum()
{
items = new int[5] { 0,2,4,6,8 };
}
public IEnumerable GetEvenNumber()
{
for (int i = 0; i < items.Length; i++)
{
yield return items[i];
}
}
}
class MainClass
{
static void Main(string[] args)
{
//顯示集合各項
ListNum mylist = new ListNum();
foreach (int i in mylist.GetEvenNumber())
{
Console.Write(i + " ");
}
}
}
}
輸出:0 2 4 6 8
為泛型列表創(chuàng)建迭代器
為泛型列表創(chuàng)建迭代器塊,要實現(xiàn)泛型接口 IEnumerator<T>),還要實現(xiàn)非泛型 GetEnumerator,因為 IEnumerable<T>) 繼承自 IEnumerable。
在類名后加個類型<T>,類里聲明了一個類型 T 的數(shù)組,并使用 Add 方法給數(shù)組賦值。在 GetEnumerator 方法中,使用 yield return 語句返回數(shù)組的值。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//導(dǎo)入命名空間
using System.Collections;
namespace MvcUsedKeywords
{
//泛型列表創(chuàng)建迭代器
class ListFive<T> : IEnumerable<T>
{
private T[] values = new T[100];
private int top = 0;
//往集合中添加元素
public void Add(T t)
{
values[top++] = t;
}
//實現(xiàn)接口IEnumerable里的GetEnumerator<T>()方法
public IEnumerator<T> GetEnumerator()
{
for (int i = top - 1; i >= 0; i--)
{
yield return values[i];
}
}
//還實現(xiàn)非泛型 GetEnumerator,因為IEnumerable(T)繼承自IEnumerable
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
class MainApp
{
static void Main(string[] args)
{
//調(diào)用為泛型列表創(chuàng)建的迭代器
ListFive<string> list5 = new ListFive<string>();
list5.Add("Red");
list5.Add("Green");
list5.Add("Blue");
Console.Write("調(diào)用泛型列表迭代器:");
foreach (string i in list5)
{
Console.Write(i + " ");
}
Console.WriteLine();
}
}
}
輸出:調(diào)用泛型列表迭代器:Red Green Blue