一文看懂IEnumerator和IEnumerable接口的區(qū)別!
IEnumerator、IEnumerable這兩個接口單詞相近、含義相關,傻傻分不清楚。
入行多年,一直沒有系統(tǒng)性梳理這對李逵李鬼。
最近本人在懟著why神的《其實吧,LRU也就那么回事》,方案1使用數(shù)組實現(xiàn)LRU,手寫算法涉及這一對接口,借此時機覆蓋這一對難纏的冤家。
IEnumerator
IEnumerator、IEnumerable接口有相似的名稱,這兩個接口通常也在一起使用,它們有不同的用途。
IEnumerator接口為類內部的集合提供了迭代方式, IEnumerator 要求你實現(xiàn)三個方法:
MoveNext方法:該方法將集合索引加1,并返回一個bool值,指示是否已到達集合的末尾。Reset方法:它將集合索引重置為其初始值-1,這會使枚舉數(shù)無效。Current方法: 返回position位置的當前對象
IEnumerable
IEnumerable接口為foreach迭代提供了支持,IEnumerable要求你實現(xiàn)GetEnumerator方法。
public?IEnumerator?GetEnumerator()
{
????return?(IEnumerator)this;
}
該用哪一個接口?
僅憑以上辭藻,很難區(qū)分兩個接口的使用場景。
IEnumerator接口定義對類中的集合類型對象的迭代方式,
IEnumerable接口允許使用foreach循環(huán)進行枚舉。
因此IEnumerable接口的GetEnumerator方法會返回一個IEnumerator接口。要實現(xiàn)IEnumerable,你還必須實現(xiàn)IEnumerator。
“從英文詞根上講:
IEnumerator接口代表了枚舉器,里面定義了枚舉方式,是名詞。
IEnumerable接口代表該對象具備了可被枚舉的性質,是形容詞。
總之,如果您想提供對foreach的支持,那么就先讓對象可枚舉,再談論枚舉方式,也就是說實現(xiàn)這兩個接口。
最佳實踐
在嵌套類中實現(xiàn)IEnumerator,這樣你可以創(chuàng)建多個枚舉器。 為IEnumerator的 Current方法提供異常處理。
為什么要這么做?
如果集合的內容發(fā)生變化,則reset方法將被調用,緊接著當前枚舉數(shù)無效,您將收到一個IndexOutOfRangeException異常(其他情況也可能導致此異常)。所以執(zhí)行一個Try…Catch塊來捕獲這個異常并引發(fā)InvalidOperationException異常, 提示在迭代時不允許修改集合內容。
“這也正是我們常見的在foreach 里面嘗試修改迭代對象會報
InvalidOperationException異常的原因。
下面以汽車列表為例實現(xiàn)IEnumerator IEnumerable接口
using?System;
using?System.Collections;
namespace?ConsoleEnum
{
????public?class?cars?:?IEnumerable
????{
????????private?car[]?carlist;
??
????????//Create?internal?array?in?constructor.
????????public?cars()
????????{
????????????carlist=?new?car[6]
????????????{
????????????????new?car("Ford",1992),
????????????????new?car("Fiat",1988),
????????????????new?car("Buick",1932),
????????????????new?car("Ford",1932),
????????????????new?car("Dodge",1999),
????????????????new?car("Honda",1977)
????????????};
????????}
????????//private?enumerator?class
????????private?class??MyEnumerator:IEnumerator
????????{
????????????public?car[]?carlist;
????????????int?position?=?-1;
????????????//constructor
????????????public?MyEnumerator(car[]?list)
????????????{
????????????????carlist=list;
????????????}
????????????private?IEnumerator?getEnumerator()
????????????{
????????????????return?(IEnumerator)this;
????????????}
????????????//IEnumerator
????????????public?bool?MoveNext()
????????????{
????????????????position++;
????????????????return?(position?????????????}
????????????//IEnumerator
????????????public?void?Reset()
????????????{
????????????????position?=?-1;
????????????}
????????????//IEnumerator
????????????public?object?Current
????????????{
????????????????get
????????????????{
????????????????????try
????????????????????{
????????????????????????return?carlist[position];
????????????????????}
????????????????????catch?(IndexOutOfRangeException)
????????????????????{
????????????????????????throw?new?InvalidOperationException();
????????????????????}
????????????????}
????????????}
????????}??//end?nested?class
??????public?IEnumerator?GetEnumerator()
??????{
??????????return?new?MyEnumerator(carlist);
??????}
????}
}


再見,VIP,臥槽又來一個看片神器!

副業(yè)剛需,個人開發(fā)者如何通過小程序變現(xiàn)?已經有朋友變現(xiàn)月入4k了!
