亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

.NetC#5.0規范:迭代器

2019-11-14 16:11:50
字體:
來源:轉載
供稿:網友

本文內容

  • 枚舉器 enumerator 接口 - IEnumerator
  • 可枚舉 enumerable 接口 - IEnumerable
  • 產生類型 yield type
  • 枚舉器 enumerator 對象 
  • 可枚舉 enumerable 對象 
  • 示例
  • 參考資料

本文只是 C# 5.0 規范中的內容,稍作調整,主要是下載 Demo 看看,這玩意用法挺多。

使用迭代器塊實現的函數成員稱為迭代器(iterator)。(所謂函數成員,包括方法、屬性、事件、索引器、用戶定義運算符、實例構造函數、靜態構造函數和析構函數。)

只要相應函數成員的返回類型是枚舉器接口 enumerator 或可枚舉接口 enumerable 之一,迭代器塊就可用作該函數成員的函數體。如下“音樂標題”類所示,有三個函數,有返回 IEnumerator 的,還有返回 IEnumerable 的,其中,返回 Reverse 函數可以反序迭代一個集合,而 Subset 函數可以迭代一個集合的子集:

public class MusicTitles
{
    string[] names = { "Tubular Bells", "Hergest Ridge", "Ommadawn", "Platinum" };
 
    public IEnumerator GetEnumerator()
    {
        for (int i = 0; i < 4; i++)
        {
            yield return names[i];
        }
    }
 
    public IEnumerable Reverse()
    {
        for (int i = 3; i >= 0; i--)
        {
            yield return names[i];
        }
    }
 
    public IEnumerable Subset(int index, int length)
    {
        for (int i = index; i < index + length; i++)
        {
            yield return names[i];
        }
    }
}

可以用如下方式迭代:

foreach (string title in titles)
{
    Console.WriteLine(title);
}
 
foreach (string title in titles.Reverse())
{
    Console.WriteLine(title);
}
 
foreach (string title in titles.Subset(2, 2))
{
    Console.WriteLine(title);
}

迭代器塊可以是 method-body、Operator-body 或 accessor-body,而不能將事件、實例構造函數、靜態構造函數和析構函數作為迭代器來實現。

當使用迭代器塊實現函數成員時,為該函數成員的形參列表指定任何 ref 或 out 形參將產生編譯時錯誤。

下載 Demo

枚舉器 enumerator 接口 - IEnumerator


枚舉器接口 (enumerator interface) 為非泛型接口 System.Collections.IEnumerator 和泛型接口 System.Collections.Generic.IEnumerator<T> 的所有實例化。

簡潔起見,將這些接口分別表示為 IEnumeratorIEnumerator<T>

可枚舉 enumerable 接口 - IEnumerable


可枚舉接口 (enumerable interface) 為非泛型接口 System.Collections.IEnumerable 和泛型接口 System.Collections.Generic.IEnumerable<T> 的所有實例化。

簡潔起見,將這些接口分別表示為 IEnumerableIEnumerable<T>。

產生類型 yield type


迭代器產生一系列值,所有值的類型均相同。此類型稱為迭代器的產生類型 (yield type)。

  • 返回 IEnumeratorIEnumerable 的迭代器的產生類型是 object。
  • 返回 IEnumerator<T> IEnumerable<T> 的迭代器的產生類型是 T。

C# 1.0 使用 foreach 語句可以迭代集合,但創建枚舉器需要大量代碼。C# 2.0 添加了 yield 語句,便于創建枚舉器。

枚舉器 enumerator 對象 


如果返回枚舉器接口類型的函數成員是使用迭代器塊實現的,調用該函數成員不會立即執行迭代器塊中的代碼。而是先創建并返回一個枚舉器對象 (enumerator object)。此對象封裝了在迭代器塊中指定的代碼,并且在調用該枚舉器對象的 MoveNext 方法時執行該迭代器塊中的代碼。枚舉器對象具有下列特點:

  • 它實現了 IEnumeratorIEnumerator<T>,其中 T 為迭代器的產生類型。
  • 它實現了 System.IDisposable
  • 它以傳遞給該函數成員的實參值(如果存在)和實例值的副本進行初始化。
  • 它有四種可能的狀態:運行前 (before)、運行中 (running)、掛起 (suspended) 和運行后 (after),并且初始狀態為運行前 (before) 狀態。

枚舉器對象通常是編譯器生成的枚舉器類的一個實例,它封裝了迭代器塊中的代碼,并實現了枚舉器接口,但也可能實現其他方法。如果枚舉器類由編譯器生成,則該類將直接或間接嵌套在包含該函數成員的類中,它將具有私有可訪問性,并且它將具有一個供編譯器使用的保留名稱。

枚舉器對象可實現除上面指定的那些接口以外的其他接口。

下面的各節將描述由枚舉器對象所提供的 IEnumerableIEnumerable<T> 接口實現的 MoveNext、CurrentDispose 成員的確切行為。

請注意,枚舉器對象不支持 IEnumerator.Reset 方法。調用此方法將導致引發 System.NotSupportedException。

MoveNext 方法

枚舉器對象的 MoveNext 方法封裝了迭代器塊的代碼。調用 MoveNext 方法將執行迭代器塊中的代碼,并相應設置枚舉器對象的 Current 屬性。MoveNext 執行的具體操作取決于調用 MoveNext 時的枚舉器對象的狀態:

  • 如果枚舉器對象的狀態為運行前 (before),則調用 MoveNext 會:
    • 將狀態更改為運行中 (running)。
    • 將迭代器塊的形參(包括 this)初始化為實參值以及初始化該枚舉器對象時所保存的實例值。
    • 從頭開始執行迭代器塊,直到執行被中斷(如后文所述)。
  • 如果枚舉器對象的狀態為運行中 (running),則調用 MoveNext 的結果不確定。
  • 如果枚舉器對象的狀態為掛起 (suspended),則調用 MoveNext 將:
    • 將狀態更改為運行中 (running)。
    • 將所有局部變量和形參(包括 this)的值恢復為迭代器塊的執行上次掛起時保存的值。注意,這些變量所引用對象的內容可能自上次調用 MoveNext 之后已經發生更改。
    • 恢復執行緊跟在引起執行掛起的 yield return 語句后面的迭代器塊,并一直繼續,直到執行中斷(如后文所述)。
  • 如果枚舉器對象的狀態為運行后 (after),則調用 MoveNext 將返回 false。

當 MoveNext 執行迭代器塊時,可以采用四種方式來中斷執行:通過 yield return 語句、通過 yield break 語句、到達迭代器塊的末尾以及引發異常并將異常傳播到迭代器塊之外。

  • 當遇到 yield return 語句時:
    • 計算該語句中給出的表達式,隱式轉換為產生類型,并賦給枚舉器對象的 Current 屬性。
    • 迭代器體的執行被掛起。所有局部變量和形參(包括 this)的值被保存,此 yield return 語句的位置也被保存。如果 yield return 語句在一個或多個 try 塊內,則此時與之關聯的 finally 塊將會執行。
    • 枚舉器對象的狀態更改為掛起 (suspended)。
    • MoveNext 方法向其調用方返回 true,指示迭代成功前進至下一個值。
  • 當遇到 yield break 語句時:
    • 如果 yield break 語句在一個或多個 try 塊內,則與之關聯的 finally 塊將執行。
    • 枚舉器對象的狀態更改為運行后 (after)。
    • MoveNext 方法向其調用方返回 false,指示迭代完成。
  • 當遇到迭代器體的結束處時:
    • 枚舉器對象的狀態更改為運行后 (after)。
    • MoveNext 方法向其調用方返回 false,指示迭代完成。
  • 當引發異常并傳播到迭代器塊之外時:
    • 通過異常傳播機制執行迭代器體內的相應 finally 塊。
    • 枚舉器對象的狀態更改為運行后 (after)。
    • 異常繼續傳播至 MoveNext 方法的調用方。

Current 屬性

枚舉器對象的 Current 屬性將受迭代器塊中的 yield return 語句影響。

當枚舉器對象處于掛起 (suspended) 狀態時,Current 的值為上一次調用 MoveNext 時設置的值。當枚舉器對象處于運行前 (before)、運行中 (running) 或運行后 (after) 狀態時,訪問 Current 的結果不確定。

對于產生類型不是 object 的迭代器,通過枚舉器對象的 IEnumerable 實現來訪問 Current 的結果對應于通過枚舉器對象的 IEnumerator<T> 實現來訪問 Current 并將該結果強制轉換為 object。

Dispose 方法

Dispose 方法用于通過使枚舉器對象變為運行后 (after) 狀態來清除迭代。

  • 如果枚舉器對象的狀態為運行前 (before),則調用 Dispose 將把狀態更改為運行后 (after)。
  • 如果枚舉器對象的狀態為運行中 (running),則調用 Dispose 的結果不確定。
  • 如果枚舉器對象的狀態為掛起 (suspended),則調用 Dispose 將:
    • 將狀態更改為運行中 (running)。
    • 執行所有 finally 塊,就像最后執行的 yield return 語句是 yield break 語句一樣。如果這導致引發異常,并且異常傳播到迭代器體之外,則枚舉器對象的狀態設置為運行后 (after),并且將異常傳播到 Dispose 方法的調用方。
    • 將狀態更改為運行后 (after)。
  • 如果枚舉器對象的狀態為運行后 (after),則調用 Dispose 沒有任何作用。

可枚舉對象 enumerable


如果返回可枚舉接口類型的函數成員是使用迭代器塊實現的,調用該函數成員不會立即執行迭代器塊中的代碼。而是先創建并返回一個可枚舉對象 (enumerable object)。可枚舉對象的 GetEnumerator 方法返回一個封裝有迭代器塊中指定的代碼的枚舉器對象,當調用該枚舉器對象的 MoveNext 方法時,將執行迭代器塊中的代碼??擅杜e對象具有下列特點:

  • 它實現了 IEnumerableIEnumerable<T>,其中 T 為迭代器的產生類型。
  • 它以傳遞給該函數成員的實參值(如果存在)和實例值的副本進行初始化。

可枚舉對象通常是編譯器生成的可枚舉類的實例,它封裝了迭代器塊中的代碼,并實現了可枚舉接口,但也可能實現其他方法。如果可枚舉類由編譯器生成,則該類將直接或間接嵌套在包含該函數成員的類中,它將具有私有可訪問性,并且它將具有供編譯器使用的保留名稱。

可枚舉對象可實現除上面指定的那些接口以外的其他接口。具體而言,可枚舉對象還可實現 IEnumerator 和 IEnumerator<T>,從而使其既可作為可枚舉對象,也可作為枚舉器對象。在該類型的實現中,首次調用可枚舉對象的 GetEnumerator 方法時,將返回可枚舉對象本身。對可枚舉對象的 GetEnumerator 的后續調用(如果存在),將返回可枚舉對象的副本。因此,每個返回的枚舉器都有自己的狀態,一個枚舉器中的更改不會影響其他枚舉器。

GetEnumerator 方法

可枚舉對象實現了 IEnumerable 和 IEnumerable<T> 接口的 GetEnumerator 方法。這兩種 GetEnumerator 方法的實現是相同的,都是獲取并返回一個可用的枚舉器對象。枚舉器對象是以初始化該可枚舉對象時保存的實例值和實參值進行初始化的,此外,枚舉器對象函數如前所述。

示例


下面的 Stack<T> 類使用一個迭代器實現其 GetEnumerator 方法。

規范中的該示例有編譯錯誤,所以采用 MSDN 中的實例:

public class Stack<T> : IEnumerable<T>
{
    PRivate T[] items;
    private int count;
 
    public void Push(T item)
    {
        if (items == null)
        {
            items = new T[4];
        }
        else if (items.Length == count)
        {
            T[] newItems = new T[count * 2];
            Array.Copy(items, 0, newItems, 0, count);
            items = newItems;
        }
        items[count++] = item;
    }
 
    public T Pop()
    {
        T result = items[--count];
        items[count] = default(T);
        return result;
    }
 
    public IEnumerator<T> GetEnumerator()
    {
        for (int i = count - 1; i >= 0; --i)
            yield return items[i];
    }
 
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
 
    public IEnumerable<T> TopToBottom
    {
        get { return this; }
    }
 
    public IEnumerable<T> BottomToTop
    {
        get
        {
            for (int index = 0; index <= count - 1; index++)
            {
                yield return items[index];
            }
        }
    }
 
    public IEnumerable<T> TopN(int itemsFromTop)
    {
        // Return less than itemsFromTop if necessary. 
        int startIndex = itemsFromTop >= count ? 0 : count - itemsFromTop;
 
        for (int index = count - 1; index >= startIndex; index--)
        {
            yield return items[index];
        }
    }
}

若用如下代碼:

Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
stack.Push(3);
stack.Push(4);
stack.Push(5);
foreach (int s in stack)
{
    Console.Write(s + " ");
}
stack.Pop();
Console.Write("/n");
foreach (int s in stack)
{
    Console.Write(s + " ");
}
Console.Write("/n");
foreach (int s in stack.TopToBottom)
{
    Console.Write(s + " ");
}
Console.Write("/n");
foreach (int s in stack.BottomToTop)
{
    Console.Write(s + " ");
}
Console.Write("/n");
foreach (int s in stack.TopN(2))
{
    Console.Write(s + " ");
}
 
Console.ReadKey();

運行結果:

5 4 3 2 1
4 3 2 1
4 3 2 1
1 2 3 4
4 3

參考資料


  • MSDN Iterators (C# and Visual Basic)
  • yield (C# Reference)
  • foreach, in (C# Reference)
  • How to: Access a Collection Class with foreach (C# Programming Guide)
  • C#5.0 規范-中文
  • C#5.0 規范-英文

 

下載 Demo


上一篇:[C#]ASCIIHelper

下一篇:webconfig初認識

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产一区在线播放| 欧美性jizz18性欧美| 亚洲精品视频免费| 热99精品里视频精品| 日本精品免费观看| 久久99精品久久久久久噜噜| 91精品国产91久久久久福利| 91精品国产91久久久久久吃药| 亚洲激情电影中文字幕| 国产做受69高潮| 国产做受69高潮| 国产日韩欧美一二三区| 欧美成人一区二区三区电影| 亚洲福利影片在线| 国产一区二区动漫| 亚洲国产成人在线视频| 精品小视频在线| 日韩欧美成人网| 欧美黄色性视频| 亚洲激情国产精品| 亚洲第一av在线| 久久久久久国产三级电影| 91久久久久久久久久久久久| 国产精品一区二区三区久久| 日韩av手机在线| 中文字幕欧美精品日韩中文字幕| 精品久久久久久中文字幕| 欧美激情一区二区三区在线视频观看| 国产精品久久国产精品99gif| 97超级碰在线看视频免费在线看| 亚洲成人中文字幕| 精品小视频在线| 欧美精品第一页在线播放| 精品国产电影一区| 宅男66日本亚洲欧美视频| 日韩在线观看免费av| 色婷婷综合成人av| 欧美日韩国产丝袜美女| 亚洲精品www久久久| 日韩精品在线免费观看视频| 亚洲欧美综合另类中字| 国产精品成人一区二区三区吃奶| 精品国产91久久久| 欧美专区在线观看| 亚洲国产成人精品女人久久久| 日韩av免费在线观看| 国产精品久久久91| 中文字幕亚洲一区在线观看| 91九色在线视频| 成人免费福利视频| 国内精品模特av私拍在线观看| 亚洲字幕一区二区| 国产日韩在线观看av| 亚洲天天在线日亚洲洲精| 国产一区二区在线免费视频| 性欧美xxxx交| 国产精品久久一区| 亚洲精品自产拍| 国产精品美腿一区在线看| 久久久999精品视频| 国产精品成av人在线视午夜片| 亚洲欧美第一页| 91香蕉嫩草神马影院在线观看| 尤物精品国产第一福利三区| 成人黄色免费看| 懂色av中文一区二区三区天美| 精品偷拍一区二区三区在线看| 日韩精品久久久久久久玫瑰园| 国产日韩精品入口| 国产精品电影网| 国产一区二区三区精品久久久| 九九久久精品一区| 亚洲石原莉奈一区二区在线观看| 久久久精品国产亚洲| 亚洲另类图片色| 国产一区二区三区视频| 国产成人高潮免费观看精品| 57pao国产成人免费| 精品女厕一区二区三区| 91av网站在线播放| 久久频这里精品99香蕉| 日韩精品极品在线观看播放免费视频| 欧美视频不卡中文| 欧美巨大黑人极品精男| 成人在线免费观看视视频| 亚洲久久久久久久久久| 国产精品国产三级国产专播精品人| 一区二区三区回区在观看免费视频| 欧美日韩亚洲精品内裤| 亚洲va男人天堂| 精品一区电影国产| 国产精品久久久久久久久久尿| 最近2019中文字幕mv免费看| 欧美精品精品精品精品免费| 曰本色欧美视频在线| 黄色成人av网| 欧美黄色小视频| 色婷婷亚洲mv天堂mv在影片| 日韩电影中文字幕av| 9.1国产丝袜在线观看| 美女精品视频一区| 日本不卡免费高清视频| 日韩视频在线一区| 久久久久久亚洲精品| www.xxxx精品| 欧美高清激情视频| 国外成人在线直播| 国产精品视频公开费视频| 午夜精品一区二区三区在线视| 久久久av免费| 国产精品99蜜臀久久不卡二区| 国产一区二区日韩精品欧美精品| 国产伊人精品在线| 日韩经典中文字幕| 欧美日韩一二三四五区| 亚洲www视频| 欧美高清电影在线看| 欧美电影电视剧在线观看| 国产精品一区二区久久久久| 国内精品久久久久久久| 国产精品www网站| 国产精品v片在线观看不卡| 国产精品视频一区二区高潮| 国产91精品视频在线观看| 国产亚洲aⅴaaaaaa毛片| 亚洲精品mp4| 国产综合香蕉五月婷在线| yellow中文字幕久久| 一区二区成人av| 国产精品福利无圣光在线一区| 国产精品99久久久久久人| 欧美一级在线亚洲天堂| 久久久精品免费视频| 午夜精品久久久久久久男人的天堂| 热久久99这里有精品| 日韩美女福利视频| 韩国美女主播一区| 欧美中文字幕在线观看| 亚洲va欧美va在线观看| 日韩在线观看免费高清| 日韩大陆欧美高清视频区| 日韩精品黄色网| 国产精品永久在线| 欧美极品少妇xxxxⅹ喷水| 97视频免费观看| 日本一本a高清免费不卡| 久久久久久久香蕉网| 自拍偷拍免费精品| 亚洲视频在线播放| 亚洲第一福利视频| 成人在线播放av| 久久影视电视剧免费网站| 国产精品白丝jk喷水视频一区| 国内自拍欧美激情| 一区二区亚洲欧洲国产日韩| 4k岛国日韩精品**专区| 影音先锋日韩有码| 日韩精品极品在线观看播放免费视频| 韩国日本不卡在线| 成人精品视频在线| 在线视频欧美性高潮| 久久久av网站| 成人黄色免费在线观看| 欧美精品久久久久久久久|