成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

.NET教程:.NET面試題之IEnumerable

.NET教程,今天給大家介紹的是:.NET 面試題之IEnumerable ,這是在面試的時(shí)候可能會(huì)碰到的一道題目,這道題的注解分為了兩個(gè)部分,這一篇是第一部分!

成都創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)由有經(jīng)驗(yàn)的網(wǎng)站設(shè)計(jì)師、開(kāi)發(fā)人員和項(xiàng)目經(jīng)理組成的專(zhuān)業(yè)建站團(tuán)隊(duì),負(fù)責(zé)網(wǎng)站視覺(jué)設(shè)計(jì)、用戶(hù)體驗(yàn)優(yōu)化、交互設(shè)計(jì)和前端開(kāi)發(fā)等方面的工作,以確保網(wǎng)站外觀(guān)精美、成都做網(wǎng)站、網(wǎng)站制作易于使用并且具有良好的響應(yīng)性。

什么是IEnumerable?

IEnumerable及IEnumerable的泛型版本IEnumerable是一個(gè)接口,它只含有一個(gè)方法GetEnumerator。Enumerable這個(gè)靜態(tài)類(lèi)型含有很多擴(kuò)展方法,其擴(kuò)展的目標(biāo)是IEnumerable。

實(shí)現(xiàn)了這個(gè)接口的類(lèi)可以使用Foreach關(guān)鍵字進(jìn)行迭代(迭代的意思是對(duì)于一個(gè)集合,可以逐一取出元素并遍歷之)。

實(shí)現(xiàn)這個(gè)接口必須實(shí)現(xiàn)方法GetEnumerator。

如何實(shí)現(xiàn)一個(gè)繼承IEnumerable的類(lèi)型?

實(shí)現(xiàn)一個(gè)繼承IEnumerable的類(lèi)型等同于實(shí)現(xiàn)方法GetEnumerator。想知道如何實(shí)現(xiàn)方法GetEnumerator,不妨思考下實(shí)現(xiàn)了GetEnumerator之后的類(lèi)型在Foreach之下的行為:

可以獲得第一個(gè)或當(dāng)前成員

可以移動(dòng)到下一個(gè)成員

可以在集合沒(méi)有下一個(gè)成員時(shí)退出循環(huán)。

假設(shè)我們有一個(gè)很簡(jiǎn)單的Person類(lèi)(例子來(lái)自MSDN):

public class Person

{

public Person(string fName, string lName)

{

FirstName = fName;

LastName = lName;

}

public string FirstName;

public string LastName;

}

然后我們想構(gòu)造一個(gè)沒(méi)有實(shí)現(xiàn)IEnumerable的類(lèi)型,其儲(chǔ)存多個(gè)Person,然后再對(duì)這個(gè)類(lèi)型實(shí)現(xiàn)IEnumerable。

這個(gè)類(lèi)型實(shí)際上的作用就相當(dāng)于Person[]或List,但我們不能使用它們,因?yàn)樗鼈円呀?jīng)實(shí)現(xiàn)了IEnumerable,故我們構(gòu)造一個(gè)People類(lèi),模擬很多人(People是Person的復(fù)數(shù)形式)。

這個(gè)類(lèi)型允許我們傳入一組Person的數(shù)組。所以它應(yīng)當(dāng)有一個(gè)Person[]類(lèi)型的成員,和一個(gè)構(gòu)造函數(shù),其可以接受一個(gè)Person[],然后將Person[]類(lèi)型的成員填充進(jìn)去作為初始化。

//People類(lèi)就是Person類(lèi)的集合

//但我們不能用List或者Person[],因?yàn)樗麄兌紝?shí)現(xiàn)了IEnumerable

//我們要自己實(shí)現(xiàn)一個(gè)IEnumerable

//所以請(qǐng)將People類(lèi)想象成List或者類(lèi)似物

public class People : IEnumerable

{

private readonly Person[] _people;

public People(Person[] pArray)

{

//構(gòu)造一個(gè)Person的集合

_people = new Person[pArray.Length];

for (var i = 0; i < pArray.Length; i++)

{

_people[i] = pArray[i];

}

}

//實(shí)現(xiàn)IEnumerable需要實(shí)現(xiàn)GetEnumerator方法

public IEnumerator GetEnumerator()

{

throw new NotImplementedException();

}

}

我們的主函數(shù)應(yīng)當(dāng)是:

public static void Main(string[] args)

{

//新的Person數(shù)組

Person[] peopleArray =

{

new Person("John", "Smith"),

new Person("Jim", "Johnson"),

new Person("Sue", "Rabon"),

};

//People類(lèi)實(shí)現(xiàn)了IEnumerable

var peopleList = new People(peopleArray);

//枚舉時(shí)先訪(fǎng)問(wèn)MoveNext方法

//如果返回真,則獲得當(dāng)前對(duì)象,返回假,就退出此次枚舉

foreach (Person p in peopleList)

Console.WriteLine(p.FirstName + " " + p.LastName);

}

但現(xiàn)在我們的程序不能運(yùn)行,因?yàn)槲覀冞€沒(méi)實(shí)現(xiàn)GetEnumerator方法。

實(shí)現(xiàn)方法GetEnumerator

GetEnumerator方法需要一個(gè)IEnumerator類(lèi)型的返回值,這個(gè)類(lèi)型是一個(gè)接口,所以我們不能這樣寫(xiě):

return new IEnumerator();

因?yàn)槲覀儾荒軐?shí)例化一個(gè)接口。我們必須再寫(xiě)一個(gè)類(lèi)PeopleEnumerator,它繼承這個(gè)接口,實(shí)現(xiàn)這個(gè)接口所有的成員:Current屬性,兩個(gè)方法MoveNext和Reset。于是我們的代碼又變成了這樣:

//實(shí)現(xiàn)IEnumerable需要實(shí)現(xiàn)GetEnumerator方法

public IEnumerator GetEnumerator()

{

return new PeopleEnumerator();

}

在類(lèi)型中:

public class PeopleEnumerator : IEnumerator

{

public bool MoveNext()

{

throw new NotImplementedException();

}

public void Reset()

{

throw new NotImplementedException();

}

public object Current { get; }

}

現(xiàn)在問(wèn)題轉(zhuǎn)移為實(shí)現(xiàn)兩個(gè)方法,它們的功能看上去一目了然:一個(gè)負(fù)責(zé)將集合中Current向后移動(dòng)一位,一個(gè)則將Current初始化為0。

我們可以查看IEnumerator元數(shù)據(jù),其解釋十分清楚:

Enumerator代表一個(gè)類(lèi)似箭頭的東西,它指向這個(gè)集合當(dāng)前迭代指向的成員

IEnumerator接口類(lèi)型對(duì)非泛型集合實(shí)現(xiàn)迭代

Current表示集合當(dāng)前的元素,我們需要用它僅有的get方法取得當(dāng)前元素

MoveNext方法根據(jù)Enumerator是否可以繼續(xù)向后移動(dòng)返回真或假

Reset方法將Enumerator移到集合的開(kāi)頭

通過(guò)上面的文字,我們可以理解GetEnumerator方法,就是獲得當(dāng)前Enumerator指向的成員。我們引入一個(gè)整型變量position來(lái)記錄當(dāng)前的位置,并且先試著寫(xiě)下:

public class PeopleEnumerator : IEnumerator

{

public Person[] _peoples;

public object Current { get; }

//當(dāng)前位置

public int position;

//構(gòu)造函數(shù)接受外部一個(gè)集合并初始化自己內(nèi)部的屬性_peoples

public PeopleEnumerator(Person[] peoples)

{

_peoples = peoples;

}

//如果沒(méi)到集合的尾部就移動(dòng)position,返回一個(gè)bool

public bool MoveNext()

{

if (position < _peoples.Length)

{

position++;

return true;

}

return false;

}

public void Reset()

{

position = 0;

}

}

這看上去好像沒(méi)問(wèn)題,但一執(zhí)行之后卻發(fā)現(xiàn):

當(dāng)執(zhí)行到MoveNext方法時(shí),position會(huì)先增加1,這導(dǎo)致第一個(gè)元素(在位置0)會(huì)被遺漏,故position的初始值應(yīng)當(dāng)為-1而不是0

當(dāng)前位置變量position顯然應(yīng)該是私有的

需要編寫(xiě)Current屬性的get方法取出當(dāng)前位置(position)上的集合成員

通過(guò)不斷的調(diào)試,最后完整的實(shí)現(xiàn)應(yīng)當(dāng)是:

public class PeopleEnumerator : IEnumerator

{

public Person[] People;

//每次運(yùn)行到MoveNext或Reset時(shí),利用get方法自動(dòng)更新當(dāng)前位置指向的對(duì)象

object IEnumerator.Current

{

get

{

try

{

//當(dāng)前位置的對(duì)象

return People[_position];

}

catch (IndexOutOfRangeException)

{

throw new InvalidOperationException();

}

}

}

//當(dāng)前位置

private int _position = -1;

public PeopleEnumerator(Person[] people)

{

People = people;

}

//當(dāng)程序運(yùn)行到foreach循環(huán)中的in時(shí),就調(diào)用這個(gè)方法獲得下一個(gè)person對(duì)象

public bool MoveNext()

{

_position++;

//返回一個(gè)布爾值,如果為真,則說(shuō)明枚舉沒(méi)有結(jié)束。

//如果為假,說(shuō)明已經(jīng)到集合的結(jié)尾,就結(jié)束此次枚舉

return (_position < People.Length);

}

public void Reset() => _position = -1;

}

為什么當(dāng)程序運(yùn)行到in時(shí),會(huì)呼叫方法MoveNext呢?我們并沒(méi)有直接調(diào)用這個(gè)方法啊?當(dāng)你試圖查詢(xún)IL時(shí),就會(huì)得到答案。實(shí)際上下面兩段代碼的作用是相同的:

foreach (T item in collection)

{

...

}

IEnumerator enumerator = collection.GetEnumerator();

while (enumerator.MoveNext())

{

T item = enumerator.Current;

...

}

注意:第二段代碼中,沒(méi)有呼叫Reset方法,也不需要呼叫。當(dāng)你呼叫時(shí),你會(huì)得到一個(gè)異常,這是因?yàn)榫幾g器沒(méi)有實(shí)現(xiàn)該方法。

新聞標(biāo)題:.NET教程:.NET面試題之IEnumerable
瀏覽地址:http://jinyejixie.com/article4/poseoe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、外貿(mào)網(wǎng)站建設(shè)、面包屑導(dǎo)航品牌網(wǎng)站建設(shè)、建站公司、品牌網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)
台州市| 东乌| 辽阳县| 张家口市| 乐都县| 大洼县| 菏泽市| 铜川市| 新民市| 凤台县| 金寨县| 连州市| 峨眉山市| 南丰县| 张北县| 天祝| 商河县| 河东区| 陇西县| 新野县| 台安县| 合江县| 柘城县| 布尔津县| 玉田县| 龙山县| 阿拉善右旗| 辽阳县| 易门县| 长武县| 乌兰浩特市| 伊川县| 东阿县| 南充市| 洛川县| 竹北市| 河曲县| 阿拉尔市| 大城县| 手游| 龙川县|