




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第8章枚舉器和迭代器8.1枚舉器8.2迭代器8.1枚舉器8.1.1枚舉器概述例如,有以下代碼:int[]myarr={1,2,3,4,5};foreach(intiteminmyarr) Console.Write("{0}",item);Console.WriteLine();其輸出是:1,2,3,4,5。為什么會這樣呢?這是因?yàn)閿?shù)組可以按需提供一個稱為枚舉器(enumerator,或枚舉數(shù))的對象。
枚舉器可用于依次讀取數(shù)組中的元素,但不能用于修改基礎(chǔ)集合,所以,不能用迭代變量(或枚舉變量)item修改myarr的元素。Array類有一個GetEnumerator方法用于返回當(dāng)前使用的枚舉器,除了Array類外,還有一些其他類型提供了GetEnumerator方法,凡是提供了GetEnumerator方法的類型稱為可枚舉類型,顯然,數(shù)組是可枚舉類型。8.1.2IEnumerator接口枚舉器是實(shí)現(xiàn)IEnumerator接口的類對象。IEnumerator接口支持對非泛型集合的簡單迭代,是所有非泛型枚舉器的基接口,它位于命名空間
System.Collections中。IEnumerator
接口有如下public成員:Current屬性:獲取集合中的當(dāng)前元素。MoveNext方法:將枚舉器推進(jìn)到集合的下一個元素。Reset方法:將枚舉器設(shè)置為其初始位置,該位置位于集合中第一個元素之前。最初,枚舉器被定位于集合中第一個元素的前面。Reset
方法用于將枚舉器返回到此位置。在此位置上,未定義
Current。
因此,在讀取
Current
的值之前,必須調(diào)用
MoveNext將枚舉數(shù)定位到集合的第一個元素。
再次調(diào)用MoveNext方法將
Current屬性定位到下一個元素。如果
MoveNext越過集合的末尾,則枚舉器將定位到集合中最后一個元素的后面,而且MoveNext返回
false。
對于前面的foreach語句的代碼,其執(zhí)行過程如下:調(diào)用arr.GetEnumerator()返回一個IEnumerator引用。調(diào)用所返回的IEnumerator接口的MoveNex方法。如果MoveNex方法返回true,就使用IEnumerator接口的屬性來獲取arr的一個元素,用于foreach循環(huán)。重復(fù)②和③的步驟,直到MoveNex方法返回false為止,此時循環(huán)停止。前面foreach語句代碼的功能與以下代碼是相同的:int[]myarr={1,2,3,4,5};Enumeratorie=myarr.GetEnumerator();while(ie.MoveNext()) Console.Write("{0}",ie.Current);Console.WriteLine();可枚舉類型myarr和默認(rèn)枚舉器8.1.3IEnumerable接口可枚舉類型是指提供了GetEnumerator方法的類型,而GetEnumerator方法是IEnumerable接口的成員,因此可枚舉類型是指實(shí)現(xiàn)了IEnumerable接口的類型。IEnumerable接口支持在非泛型集合上進(jìn)行簡單迭代,它位于
System.Collections命名空間。IEnumerable接口只有一個public成員,即GetEnumerator方法,用于返回一個循環(huán)訪問集合的枚舉器IEnumerator,而IEnumerator
可以通過集合循環(huán)顯示
Current
屬性和
MoveNext
和
Reset
方法?!纠?.1】設(shè)計(jì)一個學(xué)生類Student和一個People類,People類包含若干學(xué)生對象,通過從IEnumerable接口繼承使其成為可枚舉類型,并設(shè)計(jì)相應(yīng)的枚舉器類PeopleEnum(從IEnumerator接口繼承)。最后用foreach語句對People類對象執(zhí)行枚舉。usingSystem;usingSystem.Collections;namespaceproj8_1{publicclassStudent //聲明Student類{ publicintid; //學(xué)號 publicstringname; //姓名 publicStudent(intid,stringname) //構(gòu)造函數(shù) {this.id=id; =name; }}publicclassPeople:IEnumerable //聲明可枚舉類{privateStudent[]sts; //sts為Student對象數(shù)組publicPeople(Student[]pArray) //People類的構(gòu)造函數(shù),創(chuàng)建sts{ sts=newStudent[pArray.Length]; for(inti=0;i<pArray.Length;i++)sts[i]=pArray[i];}IEnumeratorIEnumerable.GetEnumerator()//實(shí)現(xiàn)IEnumerable的GetEnumerator方法{ return(IEnumerator)GetEnumerator(); //調(diào)用People類的GetEnumerator方法,并將結(jié)果轉(zhuǎn)換為枚舉器對象}publicPeopleEnumGetEnumerator()//定義People類的GetEnumerator{ returnnewPeopleEnum(sts);}}publicclassPeopleEnum:IEnumerator //聲明枚舉器類{publicStudent[]sts;intposition=-1; //位置字段,初始為-1publicPeopleEnum(Student[]list) //構(gòu)造函數(shù){ sts=list;}publicboolMoveNext()//定義PeopleEnum的MoveNext方法{position++;return(position<sts.Length);}publicvoidReset() //定義PeopleEnum的Reset方法{position=-1;}
objectIEnumerator.Current//實(shí)現(xiàn)IEnumerator的Current屬性{get{returnCurrent;}//返回PeopleEnum的Current屬性}publicStudentCurrent //定義PeopleEnum的Current屬性{get{returnsts[position];}//返回sts中position位置的Student對象}}classProgram{ staticvoidMain(){Student[]starry=newStudent[4] {newStudent(1,"Smith"),newStudent(2,"Johnson"),newStudent(3,"Mary"),newStudent(4,"Hammer")}; PeoplepeopleList=newPeople(starry);
foreach(StudentpinpeopleList) Console.WriteLine(p.id.ToString()+""+);}}}8.1.4泛型枚舉接口對于非泛型接口版本:IEnumerable接口的GetEnumerator方法返回實(shí)現(xiàn)IEnumerator枚舉器類的實(shí)例。實(shí)現(xiàn)IEnumerator枚舉器的類實(shí)現(xiàn)了Current屬性,它返回object的引用,然后需要把它轉(zhuǎn)換為實(shí)際類型的對象。對于泛型接口版本:IEnumerable<T>接口的GetEnumerator方法返回實(shí)現(xiàn)IEnumerator<T>枚舉器類的實(shí)例。IEnumerable<T>
是從
IEnumerable繼承的。實(shí)現(xiàn)IEnumerator<T>枚舉器的類實(shí)現(xiàn)了Current屬性,它返回實(shí)際類型的對象引用,不需要進(jìn)行轉(zhuǎn)換操作。IEnumerator<T>是從Enumerator繼承的。8.2迭代器8.2.1迭代器概述
迭代器(iterator)也是用于對集合如列表和數(shù)組等進(jìn)行迭代,它是一個代碼塊,按順序提供要在foreach循環(huán)中使用的所有值。
一般情況下,這個代碼塊是一個方法,稱為迭代器方法,也可以使用含
get訪問器的屬性來實(shí)現(xiàn)。這里的迭代器方法或
get
訪問器使用yield語句產(chǎn)生在foreach循環(huán)中使用的值。yield
語句的如下兩種形式:yieldreturn表達(dá)式:使用一個
yieldreturn
語句一次返回一個元素。foreach
循環(huán)的每次迭代都調(diào)用迭代器方法。
當(dāng)
遇到迭代器方法中的一個yieldreturn
語句時,返回“表達(dá)式”的值,并且保留代碼的當(dāng)前位置。當(dāng)下次調(diào)用迭代器方法時從該位置重新啟動。yieldbreak:使用
yieldbreak
語句結(jié)束迭代。在迭代器的迭代器方法或
get訪問器中,yieldreturn
語句的“表達(dá)式”類型必須能夠隱式轉(zhuǎn)換到迭代器返回類型。迭代器方法或
get
訪問器的聲明必須滿足以下要求:返回類型必須是
IEnumerable、IEnumerable<T>、IEnumerator或
IEnumerator<T>。該聲明不能有任何
ref
或out
參數(shù)。8.2.2迭代器方法迭代器方法不是在同一時間執(zhí)行所有語句,它只是描述了希望編譯器創(chuàng)建的枚舉器的行為,也就是說,迭代器方法的代碼描述了如何迭代元素。1.用迭代器方法實(shí)現(xiàn)可枚舉類型通過以下項(xiàng)目tmp來說明采用迭代器方法實(shí)現(xiàn)可枚舉類型的原理:usingSystem;usingSystem.Collections.Generic;namespacetmp{classProgram{ staticvoidMain(){foreach(intnumberinSomeNumbers()) Console.Write(number.ToString()+""); }publicstaticIEnumerable<int>SomeNumbers() //迭代器方法 {yieldreturn3; yieldreturn5; yieldreturn8; }}}【例8.2】設(shè)計(jì)一個程序,采用迭代器方法實(shí)現(xiàn)可枚舉類型的方式,輸出5~18之間的所有偶數(shù)。usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;namespaceProj8_2{classProgram{ publicstaticIEnumerable<int>EvenSequence(inti,intj)//迭代器方法 {for(intnumber=i;number<=j;number++) { if(number%2==0)
yieldreturnnumber; } } staticvoidMain() {foreach(intnumberinEvenSequence(5,18)) Console.Write("{0}",number); Console.WriteLine(); }}}2.用迭代器方法實(shí)現(xiàn)枚舉器可以采用創(chuàng)建枚舉器的方式,即聲明一個包含GetEnumerator方法的類,由GetEnumerator方法返回IEnumerator<int>,它通過調(diào)用迭代器方法來實(shí)現(xiàn)。前面的tmp項(xiàng)目采用迭代器方法實(shí)現(xiàn)枚舉器如下:usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;namespacetmp{classMyClass{ publicIEnumerator<int>GetEnumerator() {returnitmethod();} //返回枚舉器 publicIEnumerator<int>itmethod() //迭代器方法 {yieldreturn3; yieldreturn5; yieldreturn8; }} classProgram {staticvoidMain() { MyClasss=newMyClass(); foreach(intitemins) Console.Write("{0}",item); Console.WriteLine(); }}}輸出結(jié)果為358?!纠?.3】設(shè)計(jì)一個程序,采用迭代器方法實(shí)現(xiàn)枚舉器的方式,輸出100以內(nèi)的素?cái)?shù)。namespaceProj8_3{publicclassPrimes{ intn; publicPrimes(intn) //構(gòu)造函數(shù) {this.n=n;}
publicIEnumerator<int>GetEnumerator() {returnitmethod();} //返回枚舉器
publicIEnumerator<int>itmethod() //迭代器方法 {inti,j;boolisprime; for(i=3;i<=n;i++) {isprime=true; for(j=2;j<=(int)Math.Floor(Math.Sqrt(i));j++) {if(i%j==0) {isprime=false; break; }}if(isprime)yieldreturni; }}} classProgram {staticvoidMain(string[]args) { inti=1; Primesps=newPrimes(100); Console.WriteLine("100以內(nèi)素?cái)?shù):");
foreach(intiteminps) {Console.Write("{0,4:d}",item); if(i%10==0)//某輸出10個整數(shù)換一行 Console.WriteLine(); i++; } Console.WriteLine(); } }}從上看出,當(dāng)創(chuàng)建類的迭代器時,不必實(shí)現(xiàn)整個
IEnumerator
接口,當(dāng)編譯器檢測到迭代器時,會自動生成
Current屬性、MoveNext方法和
IEnumerator
或
IEnumerator<T>
接口的
Dispose
方法。
注意迭代器不支持
IEnumerator.Reset
方法,如果要重置迭代器,必須獲取新的迭代器。因此使用迭代器方法大大簡化了可枚舉類型和枚舉器的設(shè)計(jì)過程。8.2.3get訪問器使用get訪問器就是將迭代器作為屬性。在屬性的get訪問器中使用yieldreturn語句,這樣該屬性可以代替迭代器方法,將其返回的對象作為枚舉器。例如,前面的tmp項(xiàng)目采用get訪問器方式設(shè)計(jì)如下:usingSystem;usingSystem.Collections.Generic;namespacetmp{classProgram{ staticvoidMain() {foreach(intnumberinAttr) Console.Write(number.ToString()+""); }
publicstaticIEnumerable<int>Attr//含yieldreturn語句的屬性 {get { int[]myarr={3,5,8}; for(inti=0;i<=2;i++)
yieldreturnmyarr[i]; } }}}
【例8.5】修改例8.4的程序,增加一個正向迭代列表容器中元素的屬性和一個反向迭代列表容器中元素的屬性。usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;namespaceProj8_5{publicclassMyClass<T>:IEnumerable<T>//聲明可枚舉泛型類{ privateT[]data=newT[100]; privateintlength=0; publicvoidAdd(Te) //添加元素e {data[length]=e; length++; } IEnumeratorIEnumerable.GetEnumerator() {returnGetEnumerator();}
publicIEnumerator<T>GetEnumerator()//迭代器方法 {for(inti=0;i<=length-1;i++)
yieldreturndata[i]; }
publicIEnumerable<T>Positive {get { returnthis;} }
publicIEnumerable<T>Reverse //含yield
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年電網(wǎng)系統(tǒng)電力電纜項(xiàng)目發(fā)展計(jì)劃
- 玻璃樓梯合同范本
- Unit 5 教學(xué)設(shè)計(jì) 2024-2025學(xué)年人教版(2024)七年級英語上冊
- 2025年度數(shù)據(jù)中心冷卻系統(tǒng)維護(hù)保養(yǎng)合同范本4篇
- 2025年度品牌店鋪?zhàn)赓U經(jīng)營合同書
- 投標(biāo)法律服務(wù)方案范本
- 2025年度環(huán)保車輛租賃及綠色出行推廣合同
- Unit 5 Places(教學(xué)設(shè)計(jì))-2024-2025學(xué)年北師大版(三起)英語五年級上冊
- 2025版二手房簽一手合同范本:含房屋交易相關(guān)法律法規(guī)咨詢服務(wù)
- 2025年度醫(yī)療衛(wèi)生設(shè)備采購合同范本
- 2025年01月公安部第三研究所公開招聘人民警察筆試筆試歷年典型考題(歷年真題考點(diǎn))解題思路附帶答案詳解
- 光纜線路施工安全協(xié)議書范本
- 《我國國有企業(yè)股權(quán)融資效率實(shí)證研究》相關(guān)概念及國內(nèi)外文獻(xiàn)綜述2600字
- 2025-2030全球鋰電池用隔膜行業(yè)調(diào)研及趨勢分析報告
- 2025年湖南交通職業(yè)技術(shù)學(xué)院高職單招職業(yè)適應(yīng)性測試近5年常考版參考題庫含答案解析
- 成本合約規(guī)劃培訓(xùn)
- 交通法規(guī)教育課件
- 小學(xué)校長任期五年工作目標(biāo)(2024年-2029年)
- 2022-2024年浙江中考英語試題匯編:閱讀理解(說明文)教師版
- 第1課 中國古代政治制度的形成與發(fā)展 課件-歷史統(tǒng)編版(2019)選擇性必修1國家制度與社會治理
- 小學(xué)生思政課課件
評論
0/150
提交評論