C# 迭代器
Enumerable接口允許使用foreach循環(huán)。在foreach循環(huán)中并不是只能使用集合類,相反,在foreach循環(huán)中使用定制類通常有很多優(yōu)點。
但是,重寫使用foreach循環(huán)的方式或者提供定制的實現(xiàn)方式并不一定很簡單。為了說明這一點,下面有必要深入研究一下foreach循環(huán)。在foreach循環(huán)中,迭代一個collectionObject集合的過程如下:
(1)調(diào)用 collectionObjectGetEnumeratorO,返回一個Enumerator引用。這個方法可通過IEnumerable接口的實現(xiàn)代碼來獲得,但這是可選的。
(2)調(diào)用所返回的IEnumerator接口的MoveNextQ方法。
(3)如果MoveNextO方法返回true,就使用IEnumerator接口的Current屬性來獲取對象的一個引用,用于 foreach 循環(huán)。
(4)重復前面兩步,直到MoveNextO方法返回felse為止,此時循環(huán)停止。
所以,為在類中進行這些操作,必須重寫幾個方法,跟蹤索引,維護Qirrent屬性,以及執(zhí)行其他一些操作。這要做許多工作。
—個較簡單的替代方法是使用迭代器。使用迭代器將有效地自動生成許多代碼,正確地完成所有任務。而且,使用迭代器的語法掌握起來非常容易。
迭代器的定義是,它是一個代碼塊,按順序提供了要在foreach塊中使用的所有值。一般情況下,這個代碼塊是一個方法,但也可以使用屬性訪問器和其他代碼塊作為迭代器。這里為簡單起見,僅介紹方法。
無論代碼塊是什么,其返回類型都是有限制的。與期望正好相反,這個返回類型與所枚舉的對象類型不同。例如,在表示Animal對象集合的類中,迭代器塊的返回類型不可能是Animal。兩種可能的返回類型是前面提到的接口類型:IEnumerable和IEnumerator。使用這兩種類型的場合是:
?如果要迭代一個類,則使用方法GetEnumerator(),其返回類型是IEnumerator。
?如果要迭代一個類成員,例如一個方法,則使用IEnumerable。
在迭代器塊中,使用yield關(guān)鍵字選擇要在foreach循環(huán)中使用的值。其語法如下:
yield return <value>;
利用這個信息就足以建立一個非常簡單的示例,如下所示(該示例包含在代碼文件SimpleIterators\Program.cs中):
public static IEnumerable SimpleList()
{
yield return "string 1";
yield return "string 2";
yield return "string 3";
}
static void Main(string[] args)
{
foreach (string item in SimpleList())
WriteLine (item);
ReadKey();
}
在此,靜態(tài)方法SimpleListO就是迭代器塊。它是一個方法,所以使用IEnumerable返回類型。SimpleList()使用yieid關(guān)鍵字為使用它的foreach塊提供了 3個值,每個值都輸出到屏幕上,結(jié)果如圖所示。
顯然,這個迭代器并不是特別有用,但它確實能夠演示迭代器的機制,說明實現(xiàn)迭代器有多么簡單??纯创a,讀者可能會疑惑代碼是如何知道返回string類型的項。實際上,并沒有返回string類型的項,而是返回object類型的值。因為object是所有類型的基類,所以可從yield語句中返回任意類型。
但編譯器的智能程度很高,所以我們可以把返回值解釋為foreach循環(huán)需要的任何類型。這里代碼需要string類型的值,而這正是我們要使用的值。如果修改一行yield代碼,讓它返回一個整數(shù),就會在foreach循環(huán)中出現(xiàn)一個類型轉(zhuǎn)換異常。
對于迭代器,還有一點要注意??梢允褂孟旅娴恼Z句中斷將信息返回給foreach循環(huán)的過程:
yield break;
在遇到迭代器中的這個語句時,迭代器的處理會立即中斷,使用該迭代器的foreach循環(huán)也一樣。
點擊加載更多評論>>