国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C#基礎知識系列九(對IEnumerable和IEnumerator接口的糊涂認識)

2019-11-17 03:15:16
字體:
來源:轉載
供稿:網友

C#基礎知識系列九(對IEnumerable和IEnumerator接口的糊涂認識)

前言

  IEnumerable、IEnumerator到現在為止對這兩個接口還是不太理解,不理解但是自己總是想著試著要搞明白,畢竟自己用的少,所以在此先記錄一下。以備自己日后可以來翻查,同時也希望園子里的大牛們,來幫我看看理解的怎么樣。

查看并使用兩個接口

  接下來我們先來看看兩個接口的定義。

  先來看一下IEnumerable接口,其實看過這個接口之后,發現它其實是非常的簡單,只包含一個方法GetEnumerator(),它返回一個可用于循環訪問集合的IEnumerator對象,如下面截圖所示:

這里的IEnumerator對象,其實就是另外一個接口,這個接口對象有什么呢?它是一個真正的集合訪問器,沒有它,就不能使用foreach語句遍歷集合或數組,因為只有IEnumerator對象才能訪問集合中的項,假如連集合中的項都訪問不了,那么進行集合的循環遍歷是不可能的事情了。那么讓我們看看IEnumerator接口又定義了什么東西。

從上面我們知道IEnumerator接口定義了一個Current屬性,MoveNext和Reset兩個方法,這是多么的簡約。既然IEnumerator對象是一個訪問器。那至少應該有一個Current屬性,來獲取當前集合中的項吧。MoveNext方法只是將游標的內部位置向前移動(就是移到一下個元素而已),要想進行循環遍歷,不向前移動一下怎么行呢?

通過注釋也可以明確的發現他們的用處。

下面我們來看一個簡單的例子:

        static void Main(string[] args)        {            int[] iArr = { 1, 3, 4, 6, 7, 9 };            foreach (int i in iArr)            {                Console.WriteLine(i.ToString());            }            Console.ReadLine();        }

F5來運行代碼

結果有了,說明簡單的數組是可以支持foreach循環的。

下面我們來自己來做一個小例子,先來定義實體類

    /// <summary>    /// 個人的實體類    /// </summary>    public class Person    {        public string Name { get; set; }        public int Age { get; set; }    }    /// <summary>    /// 一群人的實體類    /// </summary>    public class People    {                    Person[] personList = new Person[4];        public People()        {            personList[0] = new Person() { Name = "aehyok", Age = 25 };            personList[1] = new Person() { Name = "Kris", Age = 22 };            personList[2] = new Person() { Name = "Leo", Age = 21 };            personList[3] = new Person() { Name = "Niki", Age = 23 };        }    }

如上面代碼所示,一個Person類是個人的實體類,然后People類是一群人的實體類,按照和上面數組類似的格式,下面我們進行調用

        static void Main(string[] args)        {       ///直接對一群人實例對象進行foreach            People people = new People();            foreach (Person p in people)            {                Console.WriteLine("Name:{0}/tAge{1}",p.Name,p.Age);            }            Console.ReadLine();        }

還沒來得及編譯,錯誤就來了

所以我們根據上面的講解我們就讓People類實現IEnumerable接口吧。現在先來修改People實體類。

    /// <summary>    /// 個人的實體類    /// </summary>    public class Person    {        public string Name { get; set; }        public int Age { get; set; }    }    /// <summary>    /// 一群人的實體類    /// </summary>    public class People:IEnumerable    {                    Person[] personList = new Person[4];        public People()        {            personList[0] = new Person() { Name = "aehyok", Age = 25 };            personList[1] = new Person() { Name = "Kris", Age = 22 };            personList[2] = new Person() { Name = "Leo", Age = 21 };            personList[3] = new Person() { Name = "Niki", Age = 23 };        }        public IEnumerator GetEnumerator()        {            return this.personList.GetEnumerator();        }    }

繼承實現接口,完成該方法之后,就可以在調用時用foreach了。

注意:其實這里完全不用繼承該接口。直接對GetEnumerator()方法進行實現,然后返回IEnumerator即可。

這樣還可以有另外一種調用方式

        static void Main(string[] args)        {            People people = new People();            foreach (Person p in people)            {                Console.WriteLine("Name:{0}/tAge{1}",p.Name,p.Age);            }            Console.WriteLine("");            ///直接獲取迭代器            IEnumerator i = people.GetEnumerator();            while (i.MoveNext())            {                Person person = (Person)i.Current;                Console.WriteLine("Name:{0}/tAge{1}", person.Name, person.Age);            }            Console.ReadLine();        }

調用結果

自定義兩個接口并進行實現

  上面我們是通過繼承微軟類庫中的接口來實現的實體集合的foreach遍歷。下面我們來演示一下完全通過自己創建接口來實現自己定義的實例集合的foreach遍歷。首先我們來實現一個簡單的迭代器。

第一步:定義一個接口IMyEnumerator,之后所有迭代器都要進行實現

    /// <summary>    /// 要求所有的迭代器全部實現該接口    /// </summary>    interface IMyEnumerator    {        bool MoveNext();        object Current{get;};    }

第二步:再定義一個接口IMyEnumerable,所有集合要實現該接口

    /// <summary>    /// 要求所有的集合實現該接口    /// 這樣一來,客戶端就可以針對該接口編碼    /// 而無須關注具體的實現    /// </summary>    interface IMyEnumerable    {        IMyEnumerator GetEnumerator();        int Count{get;};    }

第三步:一個簡單的集合類MyList,實現IMyEnumerable。

    class MyList:IMyEnumerable    {        int[] items = {0,1,2,3,4,5,6,7,8,9};        IMyEnumerator myEnumerator;        public int this[int i]        {            get { return items[i]; }            set { this.items[i] = value; }        }        public int Count        {            get { return items.Length; }        }        public IMyEnumerator GetEnumerator()        {            if (myEnumerator == null)            {                myEnumerator = new MyEnumerator(this);            }            return myEnumerator;        }    }

第四步:其實集合中也需要進行使用實現了第一步的迭代器,所以在此就是要實現這個迭代器

public class MyEnumerator:IMyEnumerator    {        int index = 0;        MyList myList;        public MyEnumerator(MyList myList)        {            this.myList = myList;        }        public bool MoveNext()        {            if (index + 1 > =myList.Count)            {                index = 1;                return false;            }            else            {                index++;                return true;            }        }        public object Current        {            get { return myList[index]; }        }    }

第五步:簡單調用進行調試

        static void Main(string[] args)        {            ///使用接口IMyEnumerable代替MyList            IMyEnumerable list = new MyList();            ///得到迭代器,在循環中針對迭代器進行編碼,而不是集合MyList            IMyEnumerator enumerator = list.GetEnumerator();            for (int i = 0; i < list.Count; i++)            {                object current = enumerator.Current;                Console.WriteLine(current.ToString());                enumerator.MoveNext();                            }            Console.WriteLine("");            ///重新創建一個新的對象            IMyEnumerable list1 = new MyList();            IMyEnumerator enumerator1 = list1.GetEnumerator();            while (enumerator1.MoveNext())    //因為此處閑下移了一位,所以從1開始            {                object current = enumerator1.Current;                Console.WriteLine(current.ToString());            }            Console.ReadLine();        }

調用結果

  其實我定義的兩個接口使用的是IMyEnumerable和IMyEnumerator,這里你直接可以去掉My那么就是微軟類庫里面的接口了,我這里只是自定義罷了,然后我自己定義接口的方法屬性,沒有嚴格按照微軟的接口進行定義,但是差不多,只需要進行簡單的修正就可以進行調用。這里有一個版本的。

View Code

其實上面例子中的調用我們就可以使用foreach來調用了,那么現在我們來用foreach來調用看看。

        static void Main(string[] args)        {            MyList list=new MyList();            foreach (object obj in list)            {                Console.WriteLine(obj.ToString());            }            Console.ReadLine();        }

總結

通過上面我實現的幾個簡單的例子可以發現,一個類型支持foreach遍歷的條件可以是:

  1、第一個方案是:這個類實現IEnumerable接口

  2、第二個方案是:這個類有一個public的GetEnumerator的實例方法(不用繼承IEnumerable實現接口),并且返回類型中有public 的bool MoveNext()實例方法和public的Current實例屬性。

實現了IEnmerable<T>接口的集合,是強類型的。它為子對象的迭代提供類型更加安全的方式。

自己實現了下,感覺還是懂了一些,雖然還沒有徹底的搞明白,但最起碼大概知道怎么回事了。有空再來看看yield關鍵字的用法。  


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 普格县| 肇东市| 杭锦旗| 潜山县| 阿城市| 准格尔旗| 中山市| 万安县| 台北县| 卢湾区| 清涧县| 大冶市| 阳信县| 永和县| 古浪县| 富宁县| 榆中县| 威信县| 应城市| 大同市| 镇康县| 古田县| 航空| 卢湾区| 江口县| 辉县市| 阳城县| 浦县| 辽阳县| 南投市| 徐水县| 芜湖市| 平湖市| 旌德县| 济源市| 怀远县| 确山县| 酒泉市| 灵寿县| 杭锦旗| 壶关县|