




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
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。為什么會這樣呢?。為什么會這樣呢? 這是因為數組可以按需提供一個稱為這是因為數組可以按需提供一個稱為枚舉器枚舉器(enumerator,或,或枚舉數枚舉數)的對象。)的對象。 枚舉器可用于依次讀取數組中的元素,但不能用于修改枚舉
2、器可用于依次讀取數組中的元素,但不能用于修改基礎集合,所以,不能用迭代變量(或枚舉變量)基礎集合,所以,不能用迭代變量(或枚舉變量)item修改修改myarr的元素。的元素。 Array類有一個類有一個GetEnumerator方法用于返回當前使用的方法用于返回當前使用的枚舉器,除了枚舉器,除了Array類外,還有一些其他類型提供了類外,還有一些其他類型提供了GetEnumerator方法方法,凡是提供了,凡是提供了GetEnumerator方法的類型方法的類型稱為可枚舉類型,顯然,數組是可枚舉類型。稱為可枚舉類型,顯然,數組是可枚舉類型。8.1.2 IEnumerator8.1.2 IEnu
3、merator接口接口 枚舉器是實現枚舉器是實現IEnumerator接口的類對象。接口的類對象。 IEnumerator接口支持對非泛型集合的簡單迭代,是所有接口支持對非泛型集合的簡單迭代,是所有非泛型枚舉器的基接口,它位于命名空間非泛型枚舉器的基接口,它位于命名空間 System.Collections中。中。IEnumerator 接口有如下接口有如下public成員:成員:lCurrent屬性:獲取集合中的當前元素。屬性:獲取集合中的當前元素。lMoveNext方法:將枚舉器推進到集合的下一個元素。方法:將枚舉器推進到集合的下一個元素。lReset方法:將枚舉器設置為其初始位置,該位置
4、位于集合中第方法:將枚舉器設置為其初始位置,該位置位于集合中第一個元素之前。一個元素之前。 最初,枚舉器被定位于集合中第一個元素的前面。最初,枚舉器被定位于集合中第一個元素的前面。Reset 方法用于將枚舉器返回到此位置。在此位置上,未定方法用于將枚舉器返回到此位置。在此位置上,未定義義 Current。 因此,在讀取因此,在讀取 Current 的值之前,必須調的值之前,必須調用用 MoveNext將枚舉數定位到集合的第一個元素。將枚舉數定位到集合的第一個元素。 再次調用再次調用MoveNext方法將方法將 Current屬性定位到下一個屬性定位到下一個元素。如果元素。如果 MoveNext
5、越過集合的末尾,則枚舉器將定位到越過集合的末尾,則枚舉器將定位到集合中最后一個元素的后面,而且集合中最后一個元素的后面,而且MoveNext返回返回 false。 對于前面的對于前面的foreach語句的代碼,其執行過程如下:語句的代碼,其執行過程如下: 調用調用arr.GetEnumerator()返回一個返回一個IEnumerator引用。引用。 調用所返回的調用所返回的IEnumerator接口的接口的MoveNex方法。方法。 如果如果MoveNex方法返回方法返回true,就使用,就使用IEnumerator接接口的屬性來獲取口的屬性來獲取arr的一個元素,用于的一個元素,用于for
6、each循環。循環。 重復和的步驟,直到重復和的步驟,直到MoveNex方法返回方法返回false為為止,此時循環停止。止,此時循環停止。前面前面foreach語句代碼的功能與以下代碼是相同的:語句代碼的功能與以下代碼是相同的:int myarr = 1, 2, 3, 4, 5 ;Enumerator ie = myarr.GetEnumerator();while (ie.MoveNext()Console.Write(0 ,ie.Current);Console.WriteLine();可枚舉類型可枚舉類型myarr和默認枚舉器和默認枚舉器8.1.3 IEnumerable8.1.3 IE
7、numerable接口接口 可枚舉類型是指提供了可枚舉類型是指提供了GetEnumerator方法的類型,而方法的類型,而GetEnumerator方法是方法是IEnumerable接口的成員,因此可枚舉接口的成員,因此可枚舉類型是指實現了類型是指實現了IEnumerable接口的類型。接口的類型。 IEnumerable接口支持在非泛型集合上進行簡單迭代,接口支持在非泛型集合上進行簡單迭代,它位于它位于 System.Collections命名空間。命名空間。IEnumerable接口只有接口只有一個一個public成員,即成員,即GetEnumerator方法,用于返回一個循環方法,用于返
8、回一個循環訪問集合的枚舉器訪問集合的枚舉器IEnumerator,而,而IEnumerator 可以通過可以通過集合循環顯示集合循環顯示 Current 屬性和屬性和 MoveNext 和和 Reset 方法。方法。 【例例8.1】設計一個學生類設計一個學生類Student和一個和一個People類,類,People類包含若干學生對象,通過從類包含若干學生對象,通過從IEnumerable 接口繼承接口繼承使其成為可枚舉類型,并設計相應的枚舉器類使其成為可枚舉類型,并設計相應的枚舉器類PeopleEnum(從(從 IEnumerator接口繼承)。最后用接口繼承)。最后用foreach語句對語
9、句對People類對象執行枚舉。類對象執行枚舉。using System;using System.Collections;namespace proj8_1 public class Student /聲明聲明Student類類 public int id; /學號學號 public string name; /姓名姓名 public Student(int id,string name) /構造函數構造函數 this.id = id; = name; public class People : IEnumerable /聲明可枚舉類聲明可枚舉類 private Stud
10、ent sts; /sts為為Student對象數組對象數組 public People(Student pArray) /People類的構造函數類的構造函數,創建創建sts sts = new StudentpArray.Length; for (int i = 0; i pArray.Length; i+) stsi = pArrayi; IEnumerator IEnumerable.GetEnumerator()/實現實現IEnumerable的的GetEnumerator方法方法 return (IEnumerator)GetEnumerator(); /調用調用People類的類
11、的GetEnumerator方法,并將結果轉換為枚舉器對象方法,并將結果轉換為枚舉器對象 public PeopleEnum GetEnumerator() /定義定義People類的類的GetEnumerator return new PeopleEnum(sts); public class PeopleEnum : IEnumerator /聲明枚舉器類聲明枚舉器類 public Student sts; int position = -1; /位置字段,初始為位置字段,初始為-1 public PeopleEnum(Student list) /構造函數構造函數 sts = list;
12、 public bool MoveNext() /定義定義PeopleEnum的的MoveNext方法方法 position+; return (position sts.Length); public void Reset() /定義定義PeopleEnum的的Reset方法方法 position = -1; object IEnumerator.Current /實現實現IEnumerator的的Current屬性屬性 get return Current; /返回返回PeopleEnum的的Current屬性屬性 public Student Current /定義定義PeopleEnu
13、m的的Current屬性屬性 get return stsposition; /返回返回sts中中position位置的位置的Student對象對象 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 泛型枚舉接口泛型枚舉接口對于對于非泛型接口版本非泛型接口版本:lIEnumerable接口的接口的GetEnumerator方法返回實現方法返回實現IEnumerator枚枚舉器類的實例。舉器類的實例。l實現實現IEnumerator枚舉器的類實現了枚舉器的類實現了Current屬性,它返回屬性,它返回object的引用,然后需要把它轉換為實際類型的對象。的引用,然后需要把它轉換為實際類型的對象。對于對于泛型接口版本泛型接口版本:lIEnumerable接口的接口的Get
15、Enumerator方法返回實現方法返回實現IEnumerator枚舉器類的實例。枚舉器類的實例。IEnumerable 是是從從 IEnumerable繼承的。繼承的。l實現實現IEnumerator枚舉器的類實現了枚舉器的類實現了Current屬性,它返回實屬性,它返回實際類型的對象引用,不需要進行轉換操作。際類型的對象引用,不需要進行轉換操作。IEnumerator是從是從Enumerator繼承的。繼承的。8.2.1 8.2.1 迭代器概述迭代器概述 迭代器迭代器(iterator)也是用于對集合如列表和數組等進)也是用于對集合如列表和數組等進行迭代,它是一個代碼塊,按順序提供要在行迭
16、代,它是一個代碼塊,按順序提供要在foreach循環循環中使用的所有值。中使用的所有值。 一般情況下,這個代碼塊是一個方法,稱為迭代器方一般情況下,這個代碼塊是一個方法,稱為迭代器方法,也可以使用含法,也可以使用含 get訪問器的屬性來實現。這里的迭代訪問器的屬性來實現。這里的迭代器方法或器方法或 get 訪問器使用訪問器使用yield語句產生在語句產生在foreach循環中使循環中使用的值。用的值。yield 語句的如下兩種形式:語句的如下兩種形式:l yield return 表達式表達式:使用一個:使用一個 yield return 語句一語句一次返回一個元素。次返回一個元素。forea
17、ch 循環的每次迭代都調用迭循環的每次迭代都調用迭代器方法。代器方法。 當當 遇到迭代器方法中的一個遇到迭代器方法中的一個yield return 語句時,返回語句時,返回“表達式表達式”的值,并且保留代的值,并且保留代碼的當前位置。當下次調用迭代器方法時從該位置碼的當前位置。當下次調用迭代器方法時從該位置重新啟動。重新啟動。l yield break:使用使用 yield break 語句結束迭代。語句結束迭代。 在迭代器的迭代器方法或在迭代器的迭代器方法或 get訪問器中,訪問器中,yield return 語語句的句的“表達式表達式”類型必須能夠隱式轉換到迭代器返回類型。類型必須能夠隱式
18、轉換到迭代器返回類型。迭代器方法或迭代器方法或 get 訪問器的聲明必須滿足以下要求:訪問器的聲明必須滿足以下要求:l 返回類型必須是返回類型必須是 IEnumerable、IEnumerable、IEnumerator或或 IEnumerator。l 該聲明不能有任何該聲明不能有任何 ref 或或out 參數。參數。8.2.2 8.2.2 迭代器方法迭代器方法 迭代器方法不是在同一時間執行所有語句,它只迭代器方法不是在同一時間執行所有語句,它只是描述了希望編譯器創建的枚舉器的行為,也就是說,是描述了希望編譯器創建的枚舉器的行為,也就是說,迭代器方法的代碼描述了如何迭代元素。迭代器方法的代碼描
19、述了如何迭代元素。1. 用迭代器方法實現可枚舉類型用迭代器方法實現可枚舉類型 通過以下項目通過以下項目tmp來說明采用迭代器方法實現可枚舉類來說明采用迭代器方法實現可枚舉類型的原理:型的原理: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】設計一個程序,采用迭代器方法實現可枚舉設計一個程序,采用迭代器方法實現可枚舉類型的方式,輸出類型的方式,輸出518之間的所有偶數。之間的所有偶數。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. 用迭代器方法實現枚舉器用迭代器方法實現枚舉器 可以采用創建枚舉器的方式,即聲明一個包含可以采用創建枚舉器的方式,即聲明一個包含GetEnumerator方法的類,由方法的類,由GetEnum
22、erator方法返回方法返回IEnumerator,它通過調用迭代器方法來實現。前面的,它通過調用迭代器方法來實現。前面的tmp項目采用迭代器方法實現枚舉器如下:項目采用迭代器方法實現枚舉器如下: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(); 輸出結果為輸出結果為3 5 8。【例例8.3】設計一個程序,采用迭代器方法實現枚舉器的方設計一個程序,采用迭代器方法實現枚舉器的方式,輸出式,輸出100以內的素數。以內的素數。namespace Proj8_3 public clas
24、s Primes int n; public Primes(int n)/構造函數構造函數 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以內素數以內素數:); foreach (int item in ps) Console.Write(0,4:d, item); if (i % 10 = 0) /某輸出某輸出10個整數換一行個整數換一行 Console.WriteLine(); i+; Console.WriteLine();
26、從上看出,當創建類的迭代器時,不必實現整從上看出,當創建類的迭代器時,不必實現整個個 IEnumerator 接口,當編譯器檢測到迭代器時,會自動生接口,當編譯器檢測到迭代器時,會自動生成成 Current屬性、屬性、MoveNext方法和方法和 IEnumerator 或或 IEnumerator 接口的接口的 Dispose 方法。方法。 注意迭代器不支持注意迭代器不支持 IEnumerator.Reset 方法方法,如果要重置,如果要重置迭代器,必須獲取新的迭代器。因此使用迭代器方法大大簡迭代器,必須獲取新的迭代器。因此使用迭代器方法大大簡化了可枚舉類型和枚舉器的設計過程。化了可枚舉類型
27、和枚舉器的設計過程。8.2.3 get8.2.3 get訪問器訪問器 使用使用get訪問器就是將迭代器作為屬性。在屬性的訪問器就是將迭代器作為屬性。在屬性的get訪問器中使用訪問器中使用yield return語句,這樣該屬性可以代替迭語句,這樣該屬性可以代替迭代器方法,將其返回的對象作為枚舉器。代器方法,將其返回的對象作為枚舉器。例如,前面的例如,前面的tmp項目采用項目采用get訪問器方式設計如下:訪問器方式設計如下: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語句的屬性語句的屬性 get int myarr = 3, 5, 8 ; for (int i = 0; i = 2; i+) yield return myarri; 【例例8.5】修改例修改例8.4的程序,增加一個正向迭代列表容器的程序,增加一個正向迭代列表容器中元素的屬性和一個反向迭代列表容器中元素的屬性。中元素的屬性和一個反向迭代列表容器中元素的屬性。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. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論