日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C# 常用接口学习 IEnumerableT

發(fā)布時間:2023/12/4 C# 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C# 常用接口学习 IEnumerableT 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我們先去看看公開的.Net4.0的源程序中IEnumerable<T>、IEnumerable、IEnumerator<T>和IEnumerator這四個接口是如何聲明的:

需加微信交流群的,請加小編微信號zls20210502,切記備注?加群,小編將會第一時間邀請你進群!目前一群滿員,只能進二群了!

????public interface IEnumerable<out T> : IEnumerable
????{
????????new IEnumerator<T> GetEnumerator();
????}

????public interface IEnumerator<out T> : IDisposable, IEnumerator
????{
????????new T Current {
????????????get;
????????}
????}

????public interface IEnumerable
????{
????????IEnumerator GetEnumerator();
????}

????public interface IEnumerator
????{
????????bool MoveNext();
????????Object Current {
????????????get;
????????}
????
????????void Reset();
????}

一、接口IEnumerable實現(xiàn)

1、建一個學生數(shù)據(jù)結構和一個學生集合類:

????//student數(shù)據(jù)結構
????class Student
????{
????????public int id;
????????public string name;
????}

????//student 集合
????class StudentCollection
????{
????????public List<Student> students = new List<Student>();
????????public void Add(Student student)
????????{
????????????students.Add(student);
????????}
????}

公開一個Add()方法以添加數(shù)據(jù),我們的集合類建立完畢。下來添加數(shù)據(jù):

????????static void Main(string[] args)
????????{
????????????StudentCollection sc = new StudentCollection();
????????????sc.Add(new Student { id=0,name="Tony"});
????????????sc.Add(new Student { id=1,name="Micheal"});
????????????sc.Add(new Student { id =2, name = "Amy" });
????????????foreach(var s in sc) {...}
????????}
????}

當我們想用foreach()遍歷的時候,編譯器會告訴我們StudentCollection不包含GetEnumerator,不能用foreach遍歷。雖然StudentCollection里面有能用遍歷的List<T>,但我們不想在屬性上迭代,我們想在類上迭代,不能?foreach(var s in sc.students){...}

現(xiàn)在只有把我們的StudentCollection類改造成能foreach的。

2、繼承接口IEnumerable:

當我們在類后面加上:IEnumerable后,Visual Studio IDE會冒出來一個小黃燈泡,點進去有提示自動填充接口的約定,我們選第一項實現(xiàn)接口(Visaul Studio是全世界最貼心的IDE!),IDE會幫我們把SudentCollection改造成以下的:

????class StudentCollection:IEnumerable
????{
????????public List<Student> students = new List<Student>();
????????public void Add(Student student)
????????{
????????????students.Add(student);
????????}

????????public IEnumerator GetEnumerator()
????????{
????????????throw new NotImplementedException();
????????}
????}

加了一個返回迭代器的方法GetEnumrator。下來按照IEnumetator接口的約定來實現(xiàn)我們的迭代器StudentCollectionEnumerator,用IDE自動補全代碼如下:

????//迭代器
????class StudentCollectionEnumerator : IEnumerator
????{
????????public object Current
????????{
????????????get
????????????{
????????????????throw new NotImplementedException();
????????????}
????????}

????????public bool MoveNext()
????????{
????????????throw new NotImplementedException();
????????}

????????public void Reset()
????????{
????????????throw new NotImplementedException();
????????}
????}

我的理解是:Current返回當前元素,MoveNext移動到下一個,Reset回到第一個元素。但根據(jù)MSDN上面的說法,Reset 方法提供的 COM 互操作性。它不一定需要實現(xiàn);相反,實施者只需拋出NotSupportedException。但是,如果您選擇執(zhí)行此操作,則應確保沒有調用方依賴于Reset功能。

迭代器工作的原理是:先調用MoveNext()方法,然后讀取Current得到元素,直到MoveNext返回false。

我們需要3個字段分別放置 元素的位置、元素、元素集。改變后的程序如下:

????//迭代器
????class StudentCollectionEnumerator : IEnumerator
????{
????????private int _index;
????????private List<Student> _collection;
????????private Student value;
????????public StudentCollectionEnumerator(List<Student> colletion)
????????{
????????????_collection = colletion;
????????????_index = -1;
????????}
???????? object IEnumerator.Current
????????{
????????????get { return value; }
????????}
????????public bool MoveNext()
????????{
????????????_index++;
????????????if (_index >= _collection.Count) { return false; }
????????????else { value = _collection[_index]; }
????????????return true;
????????}
????????public void Reset()
????????{
????????????_index = -1;
????????}

????}

首先,迭代器初始化,引入元素集 _collection,并把索引 _index設置成-1。設置成-1而不是0是因為迭代器首先調用MoveNext,在MoveNext里面我們先把索引+1指向下一個元素,如果索引_index的值初始為0,則第一個元素是元素集[1],第二個元素了。
其次,我們要把object Current改成 IEnumerator.Current,這個是實現(xiàn)迭代器的關鍵。返回元素。(好像有裝箱的行為)
第三,在MoveNext方法內(nèi)累加索引,并從元素集中讀取元素。然后讓索引值超出元素集返回個false值。
最后,在Reset方法內(nèi)讓索引值為-1,不過好像直接拋出錯誤也成。

迭代器寫好了,我們在StudentColletion類里面調用:

class StudentCollection : IEnumerable
????{
????????public List students;
????????public StudentCollection()
????????{
????????????students = new List();
????????}
????????public void Add(Student student)
????????{
????????????students.Add(student);
????????}
????????public IEnumerator GetEnumerator()
????????{
????????????return new StudentCollectionEnumerator(students);
????????}
????}

測試運行一下,大功告成!我們實現(xiàn)了可枚舉的自己的類。

通過觀察,發(fā)現(xiàn)迭代器主要就是返回一個元素對象,而StudentColletion里面的students元素集是List的,本身就能枚舉,我們能不能利用這個不用專門寫迭代器來實現(xiàn)枚舉呢?
答案是肯定的,我們這樣寫:

????class StudentCollection:IEnumerable
????{
????????public List<Student> students = new List<Student>();
????????public void Add(Student student)
????????{
????????????students.Add(student);
????????}

????????public IEnumerator GetEnumerator()
????????{
????????????foreach(var s in students)
????????????{
????????????????yield return s;
????????????}
????????}
????}

這樣就能實現(xiàn)枚舉了,真簡單,充分利用了.Net給出的各種可枚舉集合,不用再去寫GetEnumerator這種累活了。

二、接口IEnumerable<T>實現(xiàn)

如果我們想寫一個通用的可foreach的類,用到泛型:

????class MyCollection<T>
????{
????????public List<T> mycollection = new List<T>();
????????public void Add(T value)
????????{
????????????mycollection.Add(value);
????????}
????}

其實這個MyCollection類只不過是在List<T>外面封裝了一層,要實現(xiàn)IEnumable<T>,繼承該泛型接口,Visual Studio 的IDE自動幫我們補全后,如下:

????class MyCollection:IEnumerable
????{
????????public List mycollection = new List();
????????public void Add(T value)
????????{
????????????mycollection.Add(value);
????????}
????????public IEnumerator GetEnumerator()
????????{
????????????throw new NotImplementedException();
????????}
????????IEnumerator IEnumerable.GetEnumerator()
????????{
????????????throw new NotImplementedException();
????????}
????}

我們直接用上面第二個簡單的寫法,改成:

????class MyCollection:IEnumerable
????{
????????public List mycollection = new List();
????????public void Add(T value)
????????{
????????????mycollection.Add(value);
????????}
????????public IEnumerator GetEnumerator()
????????{
????????????foreach(var s in mycollection)
????????????{
????????????????yield return s;
????????????}
????????}
????????IEnumerator IEnumerable.GetEnumerator()
????????{
????????????foreach (var s in mycollection)
????????????{
????????????????yield return s;
????????????}
????????}
????}

測試運行:

???? static void Main(string[] args)
????????{
????????????MyCollection mc = new MyCollection();
????????????mc.Add(0);
????????????mc.Add(1);
????????????mc.Add(2);
????????????foreach(var s in mc) { Console.WriteLine(s); }
????????????Console.ReadKey();
????}

大功告成!
雖然第二種寫法比較投機,充分利用了.NET Framework給的各種泛型集合可枚舉的特征。不過我們也自己實現(xiàn)了一個GetEnumerator(),了解了枚舉器的工作原理。本章學習目的達成。

總結

以上是生活随笔為你收集整理的C# 常用接口学习 IEnumerableT的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。