【五分鐘的dotnet】是一個利用您的碎片化時間來學習和豐富.net知識的博文系列。它所包含了.net體系中可能會涉及到的方方面面,好比C#的小細節,AspnetCore,微服務中的.net知識等等。c#
您能夠在下班坐地鐵的時候,拿出手機逛一逛博客園,利用短短的五分鐘完成閱讀。設計模式
固然,並不意味着它篇幅短就質量差。所謂麻雀雖小五臟俱全,咱們會盡量保證利用最少的文字去詳細的闡述內容。微服務
IEnumerable和IEnumerator,若是不仔細看,是否是都覺得它們是一樣的一個單詞。特別是咱們習慣了天天看大量的中文,這種只是很小區別的單詞更是容易犯錯。學習
在.NET的世界裏好像有這種相似單詞的狀況還真的很多,好比Authentication和Authorization(認證和受權)。記得第一次見着它倆的時候,我說怎麼看了半天怎麼第一部分是它,第二個部分仍是它?甚至我一度覺得它們是同一個東西。(關於認證和受權將在後期爲你們介紹。).net
好的,回到今天的主題:IEnumerable和IEnumerator。目前咱們知道它倆是不同的東西了,至少從單詞層面(ง •_•)ง。那麼在 DotNET 中,它們扮演着怎麼樣的角色呢?設計
先來看看它們的樣子:3d
IEnumerable說:我提供了公開枚舉器,而且該枚舉器支持在非泛型集合上進行簡單迭代的功能。code
IEnumerator說:我提供了支持對非泛型集合進行簡單迭代的功能。對象
其實看接口的樣貌咱們就大概可以理解其中的奧祕了,IEnumerable 提供了能夠迭代的能力,而這種能力是經過內部的可迭代對象來實現了,這個對象就是IEnumerator。blog
因此咱們來想一下咱們在.NET中常常用到的可迭代的對象有哪些呢? 是的,你可能第一個就會想到List。那咱們就來查看IList的接口繼承關係:
public interface IList : ICollection, IEnumerable
果不其然,它繼承了IEnumerable接口。那麼這種具備了可迭代能力的對象有什麼好處呢? foreach,沒錯,它能夠享受foreach的語法糖啦。若是您瞭解過foreach的原理,您就知道,它實際上是C#爲咱們對一下代碼的包裝:
IEnumerator<string> enumeratorLst = IEnumerableClass.GetEnumerator(); while (enumeratorLst.MoveNext()) { Console.WriteLine(enumeratorLst.Current); }
因此,一層一層的抽絲剝繭,原來脫掉了品如的衣服以後,內部竟然是用了IEnumerator的各個屬性與方法之間的協做。若是您喜歡設計模式的話,您可能對這些方法再熟悉不過了,它是對迭代器模式的實現。
雙色球搖獎你們都知道吧,就一個機器在那兒嘩嘩譁,而後不斷搖啊,循環啊,而後吐出球來。因此咱們來創建這種的可迭代狀況來試試吧:
固然哈,拿雙色球舉例只是爲了好理解。賭博有風險,你懂的( ̄▽ ̄)"
先來把雙色球用咱們C#的代碼創建:
public class Ball { //球號碼 public int No { get; set; } //球顏色 public string Color { get; set; } }
而後按照上面說的,咱們是否是要讓他擁有可迭代的能力,就是要讓球可以擁有滾起來的能力,繼承IEnumerator來實現一個可迭代的雙色球迭代器對象:
public class BallEnum : IEnumerator { public Ball[] _ball; int position = -1; public BallEnum(Ball[] ball) { _ball = ball; } public bool MoveNext() { position++; return (position < _ball.Length); } public void Reset() { position = -1; } public void Dispose() { throw new NotImplementedException(); } object IEnumerator.Current { get { return Current; } } public Ball Current { get { try { return _ball[position]; } catch (IndexOutOfRangeException) { throw new InvalidOperationException(); } } } }
最後一步,給它穿上品如的衣服,將雙色球包裹,促使球去滾動,這個東西是什麼呢?好吧,它就是搖獎機,不用想它確定是繼承了IEnumerable。
public class LotteryMachine : IEnumerable { private Ball[] _balls; public LotteryMachine(Ball[] balls) { _balls = new Ball[balls.Length]; for (int i = 0; i < balls.Length; i++) { _balls[i] = balls[i]; } } // Implementation for the GetEnumerator method. IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); } public BallEnum GetEnumerator() { return new BallEnum(_balls); } }
寫好了,來看看咱們寫的這個代碼怎麼調用:
//添加兩個雙色球 Ball[] balls = new Ball[2] { new Ball() { No = 1, Color = "bule" }, new Ball() { No = 2, Color = "red" } }; //擡出咱們的搖獎機,並把球放進去 LotteryMachine lotteryMachine = new LotteryMachine(balls); //要動起來 foreach (var ball in lotteryMachine) { Console.WriteLine($"{ball.Color} + {ball.No}"); }
用C#的foreach語法糖就能夠迭代它啦,而後foreach in 出來的每個對象的類型是什麼樣子的呢?(for循環中的ball)。
是的,它是Ball類型,那麼那個BallEnum類型呢? 它隱藏起來了,咱們根本看不見啦。
原本此次想給你們分享.net core中的ValueTask和Task的,可是因爲時間有點匆忙,素材沒有收集完整,因此就只好等下次啦。
仍是那句話,但願本篇文章沒有花費您太多的時間。(ง •_•)ง