【5min+】你怎麼穿着品如的衣服?IEnumerable AND IEnumerator

系列介紹

簡介

【五分鐘的dotnet】是一個利用您的碎片化時間來學習和豐富.net知識的博文系列。它所包含了.net體系中可能會涉及到的方方面面,好比C#的小細節,AspnetCore,微服務中的.net知識等等。c#

場景

您能夠在下班坐地鐵的時候,拿出手機逛一逛博客園,利用短短的五分鐘完成閱讀。設計模式

誕生原因

  • 曾經學過的內容可能過不了多久就忘了,咱們須要一些文章來幫咱們查漏補缺。
  • 太長篇幅的文章看着滾動條就懼怕了,咱們可能更指望文字少的文章。
  • .net體系的內容太多了,平時也不知道該學哪些,咱們可能須要一點點知識線索。

文章質量

固然,並不意味着它篇幅短就質量差。所謂麻雀雖小五臟俱全,咱們會盡量保證利用最少的文字去詳細的闡述內容。微服務

正文

IEnumerableIEnumerator,若是不仔細看,是否是都覺得它們是一樣的一個單詞。特別是咱們習慣了天天看大量的中文,這種只是很小區別的單詞更是容易犯錯。學習

在.NET的世界裏好像有這種相似單詞的狀況還真的很多,好比AuthenticationAuthorization(認證和受權)。記得第一次見着它倆的時候,我說怎麼看了半天怎麼第一部分是它,第二個部分仍是它?甚至我一度覺得它們是同一個東西。(關於認證和受權將在後期爲你們介紹。).net

x

好的,回到今天的主題:IEnumerableIEnumerator。目前咱們知道它倆是不同的東西了,至少從單詞層面(ง •_•)ง。那麼在 DotNET 中,它們扮演着怎麼樣的角色呢?設計

先來看看它們的樣子:3d

x

x

IEnumerable說:我提供了公開枚舉器,而且該枚舉器支持在非泛型集合上進行簡單迭代的功能。code

IEnumerator說:我提供了支持對非泛型集合進行簡單迭代的功能。對象

其實看接口的樣貌咱們就大概可以理解其中的奧祕了,IEnumerable 提供了能夠迭代的能力,而這種能力是經過內部的可迭代對象來實現了,這個對象就是IEnumeratorblog

因此咱們來想一下咱們在.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的各個屬性與方法之間的協做。若是您喜歡設計模式的話,您可能對這些方法再熟悉不過了,它是對迭代器模式的實現。

x

實際操做一波

雙色球搖獎你們都知道吧,就一個機器在那兒嘩嘩譁,而後不斷搖啊,循環啊,而後吐出球來。因此咱們來創建這種的可迭代狀況來試試吧:

固然哈,拿雙色球舉例只是爲了好理解。賭博有風險,你懂的( ̄▽ ̄)"

s

先來把雙色球用咱們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)。

x

是的,它是Ball類型,那麼那個BallEnum類型呢? 它隱藏起來了,咱們根本看不見啦。

總結

原本此次想給你們分享.net core中的ValueTask和Task的,可是因爲時間有點匆忙,素材沒有收集完整,因此就只好等下次啦。

仍是那句話,但願本篇文章沒有花費您太多的時間。(ง •_•)ง

相關文章
相關標籤/搜索