版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第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。為什么會(huì)這樣呢?這是因?yàn)閿?shù)組可以按需提供一個(gè)稱為枚舉器(enumerator,或枚舉數(shù))的對(duì)象。
枚舉器可用于依次讀取數(shù)組中的元素,但不能用于修改基礎(chǔ)集合,所以,不能用迭代變量(或枚舉變量)item修改myarr的元素。Array類有一個(gè)GetEnumerator方法用于返回當(dāng)前使用的枚舉器,除了Array類外,還有一些其他類型提供了GetEnumerator方法,凡是提供了GetEnumerator方法的類型稱為可枚舉類型,顯然,數(shù)組是可枚舉類型。8.1.2IEnumerator接口枚舉器是實(shí)現(xiàn)IEnumerator接口的類對(duì)象。IEnumerator接口支持對(duì)非泛型集合的簡(jiǎn)單迭代,是所有非泛型枚舉器的基接口,它位于命名空間
System.Collections中。IEnumerator
接口有如下public成員:Current屬性:獲取集合中的當(dāng)前元素。MoveNext方法:將枚舉器推進(jìn)到集合的下一個(gè)元素。Reset方法:將枚舉器設(shè)置為其初始位置,該位置位于集合中第一個(gè)元素之前。最初,枚舉器被定位于集合中第一個(gè)元素的前面。Reset
方法用于將枚舉器返回到此位置。在此位置上,未定義
Current。
因此,在讀取
Current
的值之前,必須調(diào)用
MoveNext將枚舉數(shù)定位到集合的第一個(gè)元素。
再次調(diào)用MoveNext方法將
Current屬性定位到下一個(gè)元素。如果
MoveNext越過(guò)集合的末尾,則枚舉器將定位到集合中最后一個(gè)元素的后面,而且MoveNext返回
false。
對(duì)于前面的foreach語(yǔ)句的代碼,其執(zhí)行過(guò)程如下:調(diào)用arr.GetEnumerator()返回一個(gè)IEnumerator引用。調(diào)用所返回的IEnumerator接口的MoveNex方法。如果MoveNex方法返回true,就使用IEnumerator接口的屬性來(lái)獲取arr的一個(gè)元素,用于foreach循環(huán)。重復(fù)②和③的步驟,直到MoveNex方法返回false為止,此時(shí)循環(huán)停止。前面foreach語(yǔ)句代碼的功能與以下代碼是相同的: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)行簡(jiǎn)單迭代,它位于
System.Collections命名空間。IEnumerable接口只有一個(gè)public成員,即GetEnumerator方法,用于返回一個(gè)循環(huán)訪問(wèn)集合的枚舉器IEnumerator,而IEnumerator
可以通過(guò)集合循環(huán)顯示
Current
屬性和
MoveNext
和
Reset
方法?!纠?.1】設(shè)計(jì)一個(gè)學(xué)生類Student和一個(gè)People類,People類包含若干學(xué)生對(duì)象,通過(guò)從IEnumerable接口繼承使其成為可枚舉類型,并設(shè)計(jì)相應(yīng)的枚舉器類PeopleEnum(從IEnumerator接口繼承)。最后用foreach語(yǔ)句對(duì)People類對(duì)象執(zhí)行枚舉。usingSystem;usingSystem.Collections;namespaceproj8_1{publicclassStudent //聲明Student類{ publicintid; //學(xué)號(hào) publicstringname; //姓名 publicStudent(intid,stringname) //構(gòu)造函數(shù) {this.id=id; =name; }}publicclassPeople:IEnumerable //聲明可枚舉類{privateStudent[]sts; //sts為Student對(duì)象數(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)換為枚舉器對(duì)象}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對(duì)象}}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泛型枚舉接口對(duì)于非泛型接口版本:IEnumerable接口的GetEnumerator方法返回實(shí)現(xiàn)IEnumerator枚舉器類的實(shí)例。實(shí)現(xiàn)IEnumerator枚舉器的類實(shí)現(xiàn)了Current屬性,它返回object的引用,然后需要把它轉(zhuǎn)換為實(shí)際類型的對(duì)象。對(duì)于泛型接口版本:IEnumerable<T>接口的GetEnumerator方法返回實(shí)現(xiàn)IEnumerator<T>枚舉器類的實(shí)例。IEnumerable<T>
是從
IEnumerable繼承的。實(shí)現(xiàn)IEnumerator<T>枚舉器的類實(shí)現(xiàn)了Current屬性,它返回實(shí)際類型的對(duì)象引用,不需要進(jìn)行轉(zhuǎn)換操作。IEnumerator<T>是從Enumerator繼承的。8.2迭代器8.2.1迭代器概述
迭代器(iterator)也是用于對(duì)集合如列表和數(shù)組等進(jìn)行迭代,它是一個(gè)代碼塊,按順序提供要在foreach循環(huán)中使用的所有值。
一般情況下,這個(gè)代碼塊是一個(gè)方法,稱為迭代器方法,也可以使用含
get訪問(wèn)器的屬性來(lái)實(shí)現(xiàn)。這里的迭代器方法或
get
訪問(wèn)器使用yield語(yǔ)句產(chǎn)生在foreach循環(huán)中使用的值。yield
語(yǔ)句的如下兩種形式:yieldreturn表達(dá)式:使用一個(gè)
yieldreturn
語(yǔ)句一次返回一個(gè)元素。foreach
循環(huán)的每次迭代都調(diào)用迭代器方法。
當(dāng)
遇到迭代器方法中的一個(gè)yieldreturn
語(yǔ)句時(shí),返回“表達(dá)式”的值,并且保留代碼的當(dāng)前位置。當(dāng)下次調(diào)用迭代器方法時(shí)從該位置重新啟動(dòng)。yieldbreak:使用
yieldbreak
語(yǔ)句結(jié)束迭代。在迭代器的迭代器方法或
get訪問(wèn)器中,yieldreturn
語(yǔ)句的“表達(dá)式”類型必須能夠隱式轉(zhuǎn)換到迭代器返回類型。迭代器方法或
get
訪問(wèn)器的聲明必須滿足以下要求:返回類型必須是
IEnumerable、IEnumerable<T>、IEnumerator或
IEnumerator<T>。該聲明不能有任何
ref
或out
參數(shù)。8.2.2迭代器方法迭代器方法不是在同一時(shí)間執(zhí)行所有語(yǔ)句,它只是描述了希望編譯器創(chuàng)建的枚舉器的行為,也就是說(shuō),迭代器方法的代碼描述了如何迭代元素。1.用迭代器方法實(shí)現(xiàn)可枚舉類型通過(guò)以下項(xiàng)目tmp來(lái)說(shuō)明采用迭代器方法實(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ì)一個(gè)程序,采用迭代器方法實(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)建枚舉器的方式,即聲明一個(gè)包含GetEnumerator方法的類,由GetEnumerator方法返回IEnumerator<int>,它通過(guò)調(diào)用迭代器方法來(lái)實(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ì)一個(gè)程序,采用迭代器方法實(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個(gè)整數(shù)換一行 Console.WriteLine(); i++; } Console.WriteLine(); } }}從上看出,當(dāng)創(chuàng)建類的迭代器時(shí),不必實(shí)現(xiàn)整個(gè)
IEnumerator
接口,當(dāng)編譯器檢測(cè)到迭代器時(shí),會(huì)自動(dòng)生成
Current屬性、MoveNext方法和
IEnumerator
或
IEnumerator<T>
接口的
Dispose
方法。
注意迭代器不支持
IEnumerator.Reset
方法,如果要重置迭代器,必須獲取新的迭代器。因此使用迭代器方法大大簡(jiǎn)化了可枚舉類型和枚舉器的設(shè)計(jì)過(guò)程。8.2.3get訪問(wèn)器使用get訪問(wèn)器就是將迭代器作為屬性。在屬性的get訪問(wèn)器中使用yieldreturn語(yǔ)句,這樣該屬性可以代替迭代器方法,將其返回的對(duì)象作為枚舉器。例如,前面的tmp項(xiàng)目采用get訪問(wèn)器方式設(shè)計(jì)如下:usingSystem;usingSystem.Collections.Generic;namespacetmp{classProgram{ staticvoidMain() {foreach(intnumberinAttr) Console.Write(number.ToString()+""); }
publicstaticIEnumerable<int>Attr//含yieldreturn語(yǔ)句的屬性 {get { int[]myarr={3,5,8}; for(inti=0;i<=2;i++)
yieldreturnmyarr[i]; } }}}
【例8.5】修改例8.4的程序,增加一個(gè)正向迭代列表容器中元素的屬性和一個(gè)反向迭代列表容器中元素的屬性。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. 本站所有資源如無(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 在役鋼筋混凝土渡槽結(jié)構(gòu)安全評(píng)估及加固方案研究
- “郁三針”治療卒中后輕中度抑郁的臨床研究
- 含有吡喃酮的手性吲哚衍生物的設(shè)計(jì)、合成及抗菌活性研究
- 二零二五年度學(xué)校食堂食品安全管理承包協(xié)議
- 噴霧干燥法生產(chǎn)復(fù)合雜糧麥粉的工藝研究
- 2025年度物業(yè)服務(wù)賠償協(xié)議范本
- 2025年度離婚協(xié)議范本涉及婚姻財(cái)產(chǎn)分割及稅務(wù)籌劃建議
- 2025年度企業(yè)轉(zhuǎn)型股東增資擴(kuò)股協(xié)議書(shū)
- 二零二五年度冷鏈配送及食品安全保障合同
- 二零二五年度金融機(jī)構(gòu)上門(mén)收款業(yè)務(wù)合同范本
- 物業(yè)民法典知識(shí)培訓(xùn)課件
- 2023年初中畢業(yè)生信息技術(shù)中考知識(shí)點(diǎn)詳解
- 2024-2025學(xué)年八年級(jí)數(shù)學(xué)人教版上冊(cè)寒假作業(yè)(綜合復(fù)習(xí)能力提升篇)(含答案)
- 《萬(wàn)方數(shù)據(jù)資源介紹》課件
- 醫(yī)生定期考核簡(jiǎn)易程序述職報(bào)告范文(10篇)
- 第一章-地震工程學(xué)概論
- 《中國(guó)糖尿病防治指南(2024版)》更新要點(diǎn)解讀
- 交通運(yùn)輸類專業(yè)生涯發(fā)展展示
- 2024年山東省公務(wù)員錄用考試《行測(cè)》試題及答案解析
- 神經(jīng)重癥氣管切開(kāi)患者氣道功能康復(fù)與管理專家共識(shí)(2024)解讀
- 元代文學(xué)緒論
評(píng)論
0/150
提交評(píng)論