国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

C#迭代器

2019-11-17 02:30:50
字體:
供稿:網(wǎng)友

C#迭代器

1. 概述

迭代器用于遍歷集合。迭代器可定義為方法或get訪問器。在event, 實(shí)例構(gòu)造函數(shù),靜態(tài)構(gòu)造函數(shù)以及靜態(tài)析構(gòu)函數(shù)中不能使用迭代器。

yield 關(guān)鍵字專門為迭代器而設(shè)計(jì)。通過 yield定義迭代器,在實(shí)現(xiàn)IEnumerable 和 IEnumerator 接口以自定義集合時(shí)無需添加其他顯式類(保存枚舉狀態(tài))。

yield 語句有兩種形式:

yield return <exPRession>;yield break;

yield return 語句一次返回一個(gè)元素:foreach 語句或LINQ查詢每次迭代都會(huì)調(diào)用對(duì)應(yīng)迭代方法,該迭代方法運(yùn)行到 yield return 語句時(shí),會(huì)返回一個(gè)expression,并保留當(dāng)前的運(yùn)行位置,下次調(diào)用迭代器函數(shù)時(shí)直接從該位置開始。

yield break 語句用于終止迭代。

迭代器方法和get訪問器

迭代器的聲明必須滿足以下條件:

  • 返回類型必須為IEnumerable, IEnumerable<T>IEnumerator<T>.
  • 聲明中不能有ref或out參數(shù)。

返回IEnumerable或IEnumerator的迭代器,其yield類型為object。如果迭代器返回的類型為IEnumerable<T>或IEnumerator<T>,則必須把yield return語句的表達(dá)式類型隱式轉(zhuǎn)換為泛型類型參數(shù)的類型。

具有以下特點(diǎn)的方法不能包含yield returnyield break語句:

  • 匿名方法。
  • 包含unsafe塊的方法。

異常處理

不能將yield return語句放在try-catch塊中,但可以放在try-finally語句的try塊中。

yield break語句可放在try塊或catch塊中,但不能放在finally塊中。

如果foreach語句(迭代器之外)發(fā)生異常,將執(zhí)行迭代器的finally塊。

實(shí)現(xiàn)

雖然我們以方法的形式定義迭代器,但是編譯器會(huì)將其轉(zhuǎn)換為嵌套類。該類會(huì)對(duì)迭代器的位置進(jìn)行了記錄。

在為類創(chuàng)建迭代器時(shí),不用完全實(shí)現(xiàn)IEnumerator接口。當(dāng)編譯器檢測(cè)到迭代器時(shí),會(huì)自動(dòng)為生成IEnumerator或IEnumerator<T>接口的Current, MoveNext以及Dispose方法。

迭代器不支持IEnumerator.Reset方法,要重新遍歷,必須獲取一個(gè)新的迭代器。

下面代碼先從一個(gè)迭代器返回IEnumerable<string>,然后遍歷其元素:

IEnumerable<string> elements = MyIteratorMethod();foreach (string element in elements){   …}

調(diào)用MyIteratorMethod時(shí)不執(zhí)行實(shí)際操作,在foreach循環(huán)時(shí),為elements調(diào)用MoveNext方法,才真正執(zhí)行遍歷操作,直至下一個(gè)yield return 語句。

在foreach循環(huán)的每個(gè)后續(xù)迭代中,迭代器主體的執(zhí)行將從它暫停的位置繼續(xù),直至到達(dá)yield return語句后才會(huì)停止。在到達(dá)迭代器方法的結(jié)尾或yield break語句時(shí),foreach循環(huán)完成。

2. 示例

public class PowersOf2{    static void Main()    {        // Display powers of 2 up to the exponent of 8:        foreach (int i in Power(2, 8))        {            Console.Write("{0} ", i);        }    }    public static System.Collections.IEnumerable<int> Power(int number, int exponent)    {        int result = 1;        for (int i = 0; i < exponent; i++)        {            result = result * number;            yield return result;        }    }    // Output: 2 4 8 16 32 64 128 256}

上例中,for循環(huán)包含一個(gè)yield return語句。Main中的foreach循環(huán)每次迭代都會(huì)調(diào)用Power迭代器函數(shù)。對(duì)迭代器函數(shù)的每次調(diào)用都會(huì)從上次結(jié)束的地方開始。

public static class GalaxyClass{    public static void ShowGalaxies()    {        var theGalaxies = new Galaxies();        foreach (Galaxy theGalaxy in theGalaxies.NextGalaxy)        {            Debug.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears.ToString());        }    }    public class Galaxies    {        public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy        {            get            {                yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 };                yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 };                yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 };                yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 };            }        }    }    public class Galaxy    {        public String Name { get; set; }        public int MegaLightYears { get; set; }    }}
上例對(duì)get訪問器形式的迭代器進(jìn)行了演示,在該示例中,每個(gè)yield return語句返回一個(gè)用戶自定義類的實(shí)例。

2. 創(chuàng)建集合類

在例中,DaysOfTheWeek 類實(shí)現(xiàn)了IEnumerable接口,即提供GetEnumerator方法。在迭代DaysOfTheWeek集合類時(shí),編譯器會(huì)隱式調(diào)用GetEnumerator方法,得到IEnumerator。GetEnumerator方法通過yield return語句每次返回一個(gè)字符串。

static void Main(){    DaysOfTheWeek days = new DaysOfTheWeek();    foreach (string day in days)    {        Console.Write(day + " ");    }    // Output: Sun Mon Tue Wed Thu Fri Sat    Console.ReadKey();}public class DaysOfTheWeek : IEnumerable{    private string[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };    public IEnumerator GetEnumerator()    {        for (int index = 0; index < days.Length; index++)        {            // Yield each day of the week.            yield return days[index];        }    }}

3. 泛型迭代器

static void Main(){    Stack<int> theStack = new Stack<int>();    //  Add items to the stack.    for (int number = 0; number <= 9; number++)    {        theStack.Push(number);    }    // Retrieve items from the stack.    // foreach is allowed because theStack implements    // IEnumerable<int>.    foreach (int number in theStack)    {        Console.Write("{0} ", number);    }    Console.WriteLine();    // Output: 9 8 7 6 5 4 3 2 1 0    // foreach is allowed, because theStack.TopToBottom    // returns IEnumerable(Of Integer).    foreach (int number in theStack.TopToBottom)    {        Console.Write("{0} ", number);    }    Console.WriteLine();    // Output: 9 8 7 6 5 4 3 2 1 0    foreach (int number in theStack.BottomToTop)    {        Console.Write("{0} ", number);    }    Console.WriteLine();    // Output: 0 1 2 3 4 5 6 7 8 9    foreach (int number in theStack.TopN(7))    {        Console.Write("{0} ", number);    }    Console.WriteLine();    // Output: 9 8 7 6 5 4 3    Console.ReadKey();}public class Stack<T> : IEnumerable<T>{    private T[] values = new T[100];    private int top = 0;    public void Push(T t)    {        values[top] = t;        top++;    }    public T Pop()    {        top--;        return values[top];    }    // This method implements the GetEnumerator method. It allows    // an instance of the class to be used in a foreach statement.    public IEnumerator<T> GetEnumerator()    {        for (int index = top - 1; index >= 0; index--)        {            yield return values[index];        }    }    IEnumerator IEnumerable.GetEnumerator()    {        return GetEnumerator();    }    public IEnumerable<T> TopToBottom    {        get { return this; }    }    public IEnumerable<T> BottomToTop    {        get        {            for (int index = 0; index <= top - 1; index++)            {                yield return values[index];            }        }    }    public IEnumerable<T> TopN(int itemsFromTop)    {        // Return less than itemsFromTop if necessary.        int startIndex = itemsFromTop >= top ? 0 : top - itemsFromTop;        for (int index = top - 1; index >= startIndex; index--)        {            yield return values[index];        }    }}

在上面的例子中,Stack<T>泛型類實(shí)現(xiàn)了IEnumerable<T>泛型接口。Push方法將T類型值添加到數(shù)組,GetEnumerator方法通過yield return語句包含數(shù)組值。

除了泛型的GetEnumerator方法,還必須實(shí)現(xiàn)非泛型的GetEnumerator方法。因?yàn)镮Enumerable<T>從IEnumerable繼承而來。非泛型直接通過泛型實(shí)現(xiàn)。

該示例使用命名迭代器以支持對(duì)同一集合的多種迭代方式。命名迭代器包括TopToBottom,BottomToTop以及TopN方法。

其中,BottomToTop屬性在get訪問器中使用了迭代器。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 永仁县| 普兰店市| 五峰| 和政县| 都昌县| 河南省| 西畴县| 兰考县| 龙口市| 拉孜县| 邵东县| 改则县| 休宁县| 石门县| 贵州省| 雅安市| 闽侯县| 古交市| 伊金霍洛旗| 遂平县| 遂宁市| 仙游县| 泾川县| 石首市| 平凉市| 湖南省| 定襄县| 望谟县| 贵德县| 登封市| 隆回县| 筠连县| 普格县| 梧州市| 贵阳市| 铜鼓县| 安多县| 扶沟县| 河池市| 庆元县| 贺兰县|