第8章枚舉器及迭代器_第1頁(yè)
第8章枚舉器及迭代器_第2頁(yè)
第8章枚舉器及迭代器_第3頁(yè)
第8章枚舉器及迭代器_第4頁(yè)
第8章枚舉器及迭代器_第5頁(yè)
已閱讀5頁(yè),還剩28頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、8.1 8.1 枚舉器枚舉器8.2 8.2 迭代器迭代器8.1.1 8.1.1 枚舉器概述枚舉器概述例如,有以下代碼:例如,有以下代碼:int myarr = 1, 2, 3, 4, 5 ;foreach (int item in myarr)Console.Write(0 , item);Console.WriteLine();其輸出是:其輸出是:1,2,3,4,5。為什么會(huì)這樣呢?。為什么會(huì)這樣呢? 這是因?yàn)閿?shù)組可以按需提供一個(gè)稱為這是因?yàn)閿?shù)組可以按需提供一個(gè)稱為枚舉器枚舉器(enumerator,或,或枚舉數(shù)枚舉數(shù))的對(duì)象。)的對(duì)象。 枚舉器可用于依次讀取數(shù)組中的元素,但不能用于修改枚舉

2、器可用于依次讀取數(shù)組中的元素,但不能用于修改基礎(chǔ)集合,所以,不能用迭代變量(或枚舉變量)基礎(chǔ)集合,所以,不能用迭代變量(或枚舉變量)item修改修改myarr的元素。的元素。 Array類有一個(gè)類有一個(gè)GetEnumerator方法用于返回當(dāng)前使用的方法用于返回當(dāng)前使用的枚舉器,除了枚舉器,除了Array類外,還有一些其他類型提供了類外,還有一些其他類型提供了GetEnumerator方法方法,凡是提供了,凡是提供了GetEnumerator方法的類型方法的類型稱為可枚舉類型,顯然,數(shù)組是可枚舉類型。稱為可枚舉類型,顯然,數(shù)組是可枚舉類型。8.1.2 IEnumerator8.1.2 IEnu

3、merator接口接口 枚舉器是實(shí)現(xiàn)枚舉器是實(shí)現(xiàn)IEnumerator接口的類對(duì)象。接口的類對(duì)象。 IEnumerator接口支持對(duì)非泛型集合的簡(jiǎn)單迭代,是所有接口支持對(duì)非泛型集合的簡(jiǎn)單迭代,是所有非泛型枚舉器的基接口,它位于命名空間非泛型枚舉器的基接口,它位于命名空間 System.Collections中。中。IEnumerator 接口有如下接口有如下public成員:成員:lCurrent屬性:獲取集合中的當(dāng)前元素。屬性:獲取集合中的當(dāng)前元素。lMoveNext方法:將枚舉器推進(jìn)到集合的下一個(gè)元素。方法:將枚舉器推進(jìn)到集合的下一個(gè)元素。lReset方法:將枚舉器設(shè)置為其初始位置,該位置

4、位于集合中第方法:將枚舉器設(shè)置為其初始位置,該位置位于集合中第一個(gè)元素之前。一個(gè)元素之前。 最初,枚舉器被定位于集合中第一個(gè)元素的前面。最初,枚舉器被定位于集合中第一個(gè)元素的前面。Reset 方法用于將枚舉器返回到此位置。在此位置上,未定方法用于將枚舉器返回到此位置。在此位置上,未定義義 Current。 因此,在讀取因此,在讀取 Current 的值之前,必須調(diào)的值之前,必須調(diào)用用 MoveNext將枚舉數(shù)定位到集合的第一個(gè)元素。將枚舉數(shù)定位到集合的第一個(gè)元素。 再次調(diào)用再次調(diào)用MoveNext方法將方法將 Current屬性定位到下一個(gè)屬性定位到下一個(gè)元素。如果元素。如果 MoveNext

5、越過(guò)集合的末尾,則枚舉器將定位到越過(guò)集合的末尾,則枚舉器將定位到集合中最后一個(gè)元素的后面,而且集合中最后一個(gè)元素的后面,而且MoveNext返回返回 false。 對(duì)于前面的對(duì)于前面的foreach語(yǔ)句的代碼,其執(zhí)行過(guò)程如下:語(yǔ)句的代碼,其執(zhí)行過(guò)程如下: 調(diào)用調(diào)用arr.GetEnumerator()返回一個(gè)返回一個(gè)IEnumerator引用。引用。 調(diào)用所返回的調(diào)用所返回的IEnumerator接口的接口的MoveNex方法。方法。 如果如果MoveNex方法返回方法返回true,就使用,就使用IEnumerator接接口的屬性來(lái)獲取口的屬性來(lái)獲取arr的一個(gè)元素,用于的一個(gè)元素,用于for

6、each循環(huán)。循環(huán)。 重復(fù)和的步驟,直到重復(fù)和的步驟,直到MoveNex方法返回方法返回false為為止,此時(shí)循環(huán)停止。止,此時(shí)循環(huán)停止。前面前面foreach語(yǔ)句代碼的功能與以下代碼是相同的:語(yǔ)句代碼的功能與以下代碼是相同的:int myarr = 1, 2, 3, 4, 5 ;Enumerator ie = myarr.GetEnumerator();while (ie.MoveNext()Console.Write(0 ,ie.Current);Console.WriteLine();可枚舉類型可枚舉類型myarr和默認(rèn)枚舉器和默認(rèn)枚舉器8.1.3 IEnumerable8.1.3 IE

7、numerable接口接口 可枚舉類型是指提供了可枚舉類型是指提供了GetEnumerator方法的類型,而方法的類型,而GetEnumerator方法是方法是IEnumerable接口的成員,因此可枚舉接口的成員,因此可枚舉類型是指實(shí)現(xiàn)了類型是指實(shí)現(xiàn)了IEnumerable接口的類型。接口的類型。 IEnumerable接口支持在非泛型集合上進(jìn)行簡(jiǎn)單迭代,接口支持在非泛型集合上進(jìn)行簡(jiǎn)單迭代,它位于它位于 System.Collections命名空間。命名空間。IEnumerable接口只有接口只有一個(gè)一個(gè)public成員,即成員,即GetEnumerator方法,用于返回一個(gè)循環(huán)方法,用于返

8、回一個(gè)循環(huán)訪問(wèn)集合的枚舉器訪問(wèn)集合的枚舉器IEnumerator,而,而IEnumerator 可以通過(guò)可以通過(guò)集合循環(huán)顯示集合循環(huán)顯示 Current 屬性和屬性和 MoveNext 和和 Reset 方法。方法。 【例例8.1】設(shè)計(jì)一個(gè)學(xué)生類設(shè)計(jì)一個(gè)學(xué)生類Student和一個(gè)和一個(gè)People類,類,People類包含若干學(xué)生對(duì)象,通過(guò)從類包含若干學(xué)生對(duì)象,通過(guò)從IEnumerable 接口繼承接口繼承使其成為可枚舉類型,并設(shè)計(jì)相應(yīng)的枚舉器類使其成為可枚舉類型,并設(shè)計(jì)相應(yīng)的枚舉器類PeopleEnum(從(從 IEnumerator接口繼承)。最后用接口繼承)。最后用foreach語(yǔ)句對(duì)語(yǔ)

9、句對(duì)People類對(duì)象執(zhí)行枚舉。類對(duì)象執(zhí)行枚舉。using System;using System.Collections;namespace proj8_1 public class Student /聲明聲明Student類類 public int id; /學(xué)號(hào)學(xué)號(hào) public string name; /姓名姓名 public Student(int id,string name) /構(gòu)造函數(shù)構(gòu)造函數(shù) this.id = id; = name; public class People : IEnumerable /聲明可枚舉類聲明可枚舉類 private Stud

10、ent sts; /sts為為Student對(duì)象數(shù)組對(duì)象數(shù)組 public People(Student pArray) /People類的構(gòu)造函數(shù)類的構(gòu)造函數(shù),創(chuàng)建創(chuàng)建sts sts = new StudentpArray.Length; for (int i = 0; i pArray.Length; i+) stsi = pArrayi; IEnumerator IEnumerable.GetEnumerator()/實(shí)現(xiàn)實(shí)現(xiàn)IEnumerable的的GetEnumerator方法方法 return (IEnumerator)GetEnumerator(); /調(diào)用調(diào)用People類的類

11、的GetEnumerator方法,并將結(jié)果轉(zhuǎn)換為枚舉器對(duì)象方法,并將結(jié)果轉(zhuǎn)換為枚舉器對(duì)象 public PeopleEnum GetEnumerator() /定義定義People類的類的GetEnumerator return new PeopleEnum(sts); public class PeopleEnum : IEnumerator /聲明枚舉器類聲明枚舉器類 public Student sts; int position = -1; /位置字段,初始為位置字段,初始為-1 public PeopleEnum(Student list) /構(gòu)造函數(shù)構(gòu)造函數(shù) sts = list;

12、 public bool MoveNext() /定義定義PeopleEnum的的MoveNext方法方法 position+; return (position sts.Length); public void Reset() /定義定義PeopleEnum的的Reset方法方法 position = -1; object IEnumerator.Current /實(shí)現(xiàn)實(shí)現(xiàn)IEnumerator的的Current屬性屬性 get return Current; /返回返回PeopleEnum的的Current屬性屬性 public Student Current /定義定義PeopleEnu

13、m的的Current屬性屬性 get return stsposition; /返回返回sts中中position位置的位置的Student對(duì)象對(duì)象 class Program static void Main() Student starry = new Student4 new Student(1, Smith),new Student(2, Johnson), new Student(3,Mary),new Student(4,Hammer) ; People peopleList = new People(starry); foreach (Student p in peopleLis

14、t) Console.WriteLine(p.id.ToString() + + ); 8.1.4 8.1.4 泛型枚舉接口泛型枚舉接口對(duì)于對(duì)于非泛型接口版本非泛型接口版本:lIEnumerable接口的接口的GetEnumerator方法返回實(shí)現(xiàn)方法返回實(shí)現(xiàn)IEnumerator枚枚舉器類的實(shí)例。舉器類的實(shí)例。l實(shí)現(xiàn)實(shí)現(xiàn)IEnumerator枚舉器的類實(shí)現(xiàn)了枚舉器的類實(shí)現(xiàn)了Current屬性,它返回屬性,它返回object的引用,然后需要把它轉(zhuǎn)換為實(shí)際類型的對(duì)象。的引用,然后需要把它轉(zhuǎn)換為實(shí)際類型的對(duì)象。對(duì)于對(duì)于泛型接口版本泛型接口版本:lIEnumerable接口的接口的Get

15、Enumerator方法返回實(shí)現(xiàn)方法返回實(shí)現(xiàn)IEnumerator枚舉器類的實(shí)例。枚舉器類的實(shí)例。IEnumerable 是是從從 IEnumerable繼承的。繼承的。l實(shí)現(xiàn)實(shí)現(xiàn)IEnumerator枚舉器的類實(shí)現(xiàn)了枚舉器的類實(shí)現(xiàn)了Current屬性,它返回實(shí)屬性,它返回實(shí)際類型的對(duì)象引用,不需要進(jìn)行轉(zhuǎn)換操作。際類型的對(duì)象引用,不需要進(jìn)行轉(zhuǎn)換操作。IEnumerator是從是從Enumerator繼承的。繼承的。8.2.1 8.2.1 迭代器概述迭代器概述 迭代器迭代器(iterator)也是用于對(duì)集合如列表和數(shù)組等進(jìn))也是用于對(duì)集合如列表和數(shù)組等進(jìn)行迭代,它是一個(gè)代碼塊,按順序提供要在行迭

16、代,它是一個(gè)代碼塊,按順序提供要在foreach循環(huán)循環(huán)中使用的所有值。中使用的所有值。 一般情況下,這個(gè)代碼塊是一個(gè)方法,稱為迭代器方一般情況下,這個(gè)代碼塊是一個(gè)方法,稱為迭代器方法,也可以使用含法,也可以使用含 get訪問(wèn)器的屬性來(lái)實(shí)現(xiàn)。這里的迭代訪問(wèn)器的屬性來(lái)實(shí)現(xiàn)。這里的迭代器方法或器方法或 get 訪問(wèn)器使用訪問(wèn)器使用yield語(yǔ)句產(chǎn)生在語(yǔ)句產(chǎn)生在foreach循環(huán)中使循環(huán)中使用的值。用的值。yield 語(yǔ)句的如下兩種形式:語(yǔ)句的如下兩種形式:l yield return 表達(dá)式表達(dá)式:使用一個(gè):使用一個(gè) yield return 語(yǔ)句一語(yǔ)句一次返回一個(gè)元素。次返回一個(gè)元素。forea

17、ch 循環(huán)的每次迭代都調(diào)用迭循環(huán)的每次迭代都調(diào)用迭代器方法。代器方法。 當(dāng)當(dāng) 遇到迭代器方法中的一個(gè)遇到迭代器方法中的一個(gè)yield return 語(yǔ)句時(shí),返回語(yǔ)句時(shí),返回“表達(dá)式表達(dá)式”的值,并且保留代的值,并且保留代碼的當(dāng)前位置。當(dāng)下次調(diào)用迭代器方法時(shí)從該位置碼的當(dāng)前位置。當(dāng)下次調(diào)用迭代器方法時(shí)從該位置重新啟動(dòng)。重新啟動(dòng)。l yield break:使用使用 yield break 語(yǔ)句結(jié)束迭代。語(yǔ)句結(jié)束迭代。 在迭代器的迭代器方法或在迭代器的迭代器方法或 get訪問(wèn)器中,訪問(wèn)器中,yield return 語(yǔ)語(yǔ)句的句的“表達(dá)式表達(dá)式”類型必須能夠隱式轉(zhuǎn)換到迭代器返回類型。類型必須能夠隱式

18、轉(zhuǎn)換到迭代器返回類型。迭代器方法或迭代器方法或 get 訪問(wèn)器的聲明必須滿足以下要求:訪問(wèn)器的聲明必須滿足以下要求:l 返回類型必須是返回類型必須是 IEnumerable、IEnumerable、IEnumerator或或 IEnumerator。l 該聲明不能有任何該聲明不能有任何 ref 或或out 參數(shù)。參數(shù)。8.2.2 8.2.2 迭代器方法迭代器方法 迭代器方法不是在同一時(shí)間執(zhí)行所有語(yǔ)句,它只迭代器方法不是在同一時(shí)間執(zhí)行所有語(yǔ)句,它只是描述了希望編譯器創(chuàng)建的枚舉器的行為,也就是說(shuō),是描述了希望編譯器創(chuàng)建的枚舉器的行為,也就是說(shuō),迭代器方法的代碼描述了如何迭代元素。迭代器方法的代碼描

19、述了如何迭代元素。1. 用迭代器方法實(shí)現(xiàn)可枚舉類型用迭代器方法實(shí)現(xiàn)可枚舉類型 通過(guò)以下項(xiàng)目通過(guò)以下項(xiàng)目tmp來(lái)說(shuō)明采用迭代器方法實(shí)現(xiàn)可枚舉類來(lái)說(shuō)明采用迭代器方法實(shí)現(xiàn)可枚舉類型的原理:型的原理:using System;using System.Collections.Generic;namespace tmp class Program static void Main() foreach (int number in SomeNumbers() Console.Write(number.ToString() + ); public static IEnumerable SomeNumbers

20、()/迭代器方法迭代器方法 yield return 3; yield return 5; yield return 8; 【例例8.2】設(shè)計(jì)一個(gè)程序,采用迭代器方法實(shí)現(xiàn)可枚舉設(shè)計(jì)一個(gè)程序,采用迭代器方法實(shí)現(xiàn)可枚舉類型的方式,輸出類型的方式,輸出518之間的所有偶數(shù)。之間的所有偶數(shù)。using System;using System.Collections;using System.Collections.Generic;namespace Proj8_2 class Program public static IEnumerable EvenSequence(int i, int j) /迭

21、代器方法迭代器方法 for (int number = i; number = j; number+) if (number % 2 = 0) yield return number; static void Main() foreach (int number in EvenSequence(5, 18) Console.Write(0 ,number); Console.WriteLine(); 2. 用迭代器方法實(shí)現(xiàn)枚舉器用迭代器方法實(shí)現(xiàn)枚舉器 可以采用創(chuàng)建枚舉器的方式,即聲明一個(gè)包含可以采用創(chuàng)建枚舉器的方式,即聲明一個(gè)包含GetEnumerator方法的類,由方法的類,由GetEnum

22、erator方法返回方法返回IEnumerator,它通過(guò)調(diào)用迭代器方法來(lái)實(shí)現(xiàn)。前面的,它通過(guò)調(diào)用迭代器方法來(lái)實(shí)現(xiàn)。前面的tmp項(xiàng)目采用迭代器方法實(shí)現(xiàn)枚舉器如下:項(xiàng)目采用迭代器方法實(shí)現(xiàn)枚舉器如下:using System;using System.Collections;using System.Collections.Generic;namespace tmp class MyClass public IEnumerator GetEnumerator() return itmethod(); /返回枚舉器返回枚舉器 public IEnumerator itmethod() /迭代器方法迭

23、代器方法 yield return 3; yield return 5; yield return 8; class Program static void Main() MyClass s = new MyClass(); foreach (int item in s) Console.Write(0 , item); Console.WriteLine(); 輸出結(jié)果為輸出結(jié)果為3 5 8。【例例8.3】設(shè)計(jì)一個(gè)程序,采用迭代器方法實(shí)現(xiàn)枚舉器的方設(shè)計(jì)一個(gè)程序,采用迭代器方法實(shí)現(xiàn)枚舉器的方式,輸出式,輸出100以內(nèi)的素?cái)?shù)。以內(nèi)的素?cái)?shù)。namespace Proj8_3 public clas

24、s Primes int n; public Primes(int n)/構(gòu)造函數(shù)構(gòu)造函數(shù) this.n = n; public IEnumerator GetEnumerator() return itmethod(); /返回枚舉器返回枚舉器 public IEnumerator itmethod() /迭代器方法迭代器方法 int i,j; bool isprime; for (i = 3; i = n; i+) isprime = true; for (j = 2; j = (int)Math.Floor(Math.Sqrt(i); j+) if (i % j = 0) isprime

25、 = false; break; if (isprime) yield return i; class Program static void Main(string args) int i = 1; Primes ps = new Primes(100); Console.WriteLine(100以內(nèi)素?cái)?shù)以內(nèi)素?cái)?shù):); foreach (int item in ps) Console.Write(0,4:d, item); if (i % 10 = 0) /某輸出某輸出10個(gè)整數(shù)換一行個(gè)整數(shù)換一行 Console.WriteLine(); i+; Console.WriteLine();

26、從上看出,當(dāng)創(chuàng)建類的迭代器時(shí),不必實(shí)現(xiàn)整從上看出,當(dāng)創(chuàng)建類的迭代器時(shí),不必實(shí)現(xiàn)整個(gè)個(gè) IEnumerator 接口,當(dāng)編譯器檢測(cè)到迭代器時(shí),會(huì)自動(dòng)生接口,當(dāng)編譯器檢測(cè)到迭代器時(shí),會(huì)自動(dòng)生成成 Current屬性、屬性、MoveNext方法和方法和 IEnumerator 或或 IEnumerator 接口的接口的 Dispose 方法。方法。 注意迭代器不支持注意迭代器不支持 IEnumerator.Reset 方法方法,如果要重置,如果要重置迭代器,必須獲取新的迭代器。因此使用迭代器方法大大簡(jiǎn)迭代器,必須獲取新的迭代器。因此使用迭代器方法大大簡(jiǎn)化了可枚舉類型和枚舉器的設(shè)計(jì)過(guò)程?;丝擅杜e類型

27、和枚舉器的設(shè)計(jì)過(guò)程。8.2.3 get8.2.3 get訪問(wèn)器訪問(wèn)器 使用使用get訪問(wèn)器就是將迭代器作為屬性。在屬性的訪問(wèn)器就是將迭代器作為屬性。在屬性的get訪問(wèn)器中使用訪問(wèn)器中使用yield return語(yǔ)句,這樣該屬性可以代替迭語(yǔ)句,這樣該屬性可以代替迭代器方法,將其返回的對(duì)象作為枚舉器。代器方法,將其返回的對(duì)象作為枚舉器。例如,前面的例如,前面的tmp項(xiàng)目采用項(xiàng)目采用get訪問(wèn)器方式設(shè)計(jì)如下:訪問(wèn)器方式設(shè)計(jì)如下:using System;using System.Collections.Generic;namespace tmp class Program static void M

28、ain() foreach (int number in Attr) Console.Write(number.ToString() + ); public static IEnumerable Attr /含含yield return語(yǔ)句的屬性語(yǔ)句的屬性 get int myarr = 3, 5, 8 ; for (int i = 0; i = 2; i+) yield return myarri; 【例例8.5】修改例修改例8.4的程序,增加一個(gè)正向迭代列表容器的程序,增加一個(gè)正向迭代列表容器中元素的屬性和一個(gè)反向迭代列表容器中元素的屬性。中元素的屬性和一個(gè)反向迭代列表容器中元素的屬性。using System;using System.Collections;using System.Collections.Generic;namespace Proj8_5 public class MyClass : IEnumerable/聲明可枚舉泛型類聲明可枚舉泛型類 private T data = new T100; private int length = 0; public void Add(T e) /添加元素添加元素e datalength =

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論