前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C# 通过IEnumberable接口和IEnumerator接口实现自定义集合类型foreach功能

C# 通过IEnumberable接口和IEnumerator接口实现自定义集合类型foreach功能

作者头像
郑小超.
发布2018-01-26 15:57:48
8860
发布2018-01-26 15:57:48
举报
文章被收录于专栏:GreenLeavesGreenLeaves

1、IEnumerator和IEnumerable的作用

其实IEnumerator和IEnumerable的作用很简单,就是让除数组和集合之外的类型也能支持foreach循环,至于foreach循环,如果不清楚,请参考C# foreach循环较for循环的优势与劣势

代码如下:

代码语言:javascript
复制
static void Main(string[] args)
{
       CatList cats = new CatList();
       foreach (var cat in cats)
       {
            Console.WriteLine(cat.NickName);
       }
}

public class CatList
{
       public string NickName { get; set; }
       public int Age { get; set; }
}

以上代码说明自定义集合类型(假设CatList是集合类型)是无法使用foreach进行循环的.

原因是C#中自定义集合类型要实现foreach的功能,必须通过IEnumerator和IEnumerable两个接口来实现!

2、通过IEnumerator和IEnumerable两个接口实现自定义集合类型的foreach循环功能.

第一步:实现自定义集合类型实现IEnumerable接口,实现该接口的字面意思可以理解为:自定义集合类型实现了该接口,就拥有了"可枚举的功能".代码如下:

实现了IEnumerable接口之后,发现该接口规定必须返回一个IEnumerator接口(迭代器对象).ok,那么就必须返回一个IEnumerator,那么它是什么呢?别急,下面开始介绍这个接口!

第二步:通过IEnumerable要求实现的GetEnumerator()方法返回一个IEnumerator(迭代器对象),实现该接口必须实现以下三个方法/属性:

(1)、MoveNext()   ---将当前遍历的枚举数推进到集合的下一个.

注:如果 MoveNext 越过集合的末尾,则枚举数将被放置在此集合中最后一个元素的后面,而且 MoveNext 返回 false。当枚举数位于此位置时,对MoveNext 的后续调用也返回 false。如果最后一次调用 MoveNext 返回 false,则调用 Current 会引发异常。若要再次将 Current 设置为集合的第一个元素,可以调用 Reset,然后再调用 MoveNext

(2)、Current属性   ---返回正在遍历的集合中的元素

(3)、Reset()   ---重置当前正在遍历的集合中元素的索引.

第三步:具体实现

在介绍完上面两个接口之后,开始具体的实现,现在需要编写一个People类,该类是一个Person集合,要求People类拥有foreach循环的功能,代码如下:

代码语言:javascript
复制
public class People : IEnumerable
    {
        private Person[] persons;

        public People(Person[] persons)
        {
            Persons = persons;
        }

        public Person[] Persons { get => persons; set => persons = value; }

        public IEnumerator GetEnumerator()
        {
            return new PersonEnum(Persons);
        }

        public class PersonEnum : IEnumerator
        {
            private Person[] perons;
            private int _index=-1;

            public PersonEnum(Person[] persons)
            {
                Perons = persons;
            }

            public object Current => Perons[_index];

            public Person[] Perons { get => perons; set => perons = value; }

            public bool MoveNext()
            {
                _index++;
                if (_index < perons.Length)
                    return true;
                else
                    return false;
            }

            public void Reset()
            {
                _index = 0;
            }
        }
    }

第四步:验证代码,代码如下:

代码语言:javascript
复制
Person[] persons ={
         new Person(){FirstName="Stephen",LastName="Curry"},
         new Person(){FirstName="Lebron",LastName="James"},
         new Person(){FirstName="Kobe",LastName="Brant"}
};
People people = new People(persons);
foreach (var p in people)
{
     Console.WriteLine(((Person)p).LastName);
}

第五步:分析原理

总结分析下上面的代码,实现foreach代码的基本原理如下:

1、编写自定义集合类,实现IEnumerable接口,通过GetEnumerator()方法返回一个迭代器对象实例.

2、通过自定义集合类的构造函数,或者方法,或者属性(都可以),初始化一个类数组   !Important

3、将初始化完的类数组作为参数传递给迭代器类

4、编写迭代器类,create 构造函数,接收自定义集合类初始化完的类数组

5、实现IEnumerator(迭代器)接口,实现对应的三个方法,通过编写三个方法发现,其实迭代器就是简单的对数组进行的操作

第六步:思考

经过上面的分析之后,发现其实foreach语句换成C#代码就是以下代码:

代码语言:javascript
复制
Person[] persons ={
         new Person(){FirstName="Stephen",LastName="Curry"},
         new Person(){FirstName="Lebron",LastName="James"},
         new Person(){FirstName="Kobe",LastName="Brant"}
};

People people = new People(persons);
IEnumerator er = people.GetEnumerator();
while (er.MoveNext())
{
     Console.WriteLine(((Person)er.Current).LastName);
}

其实foreach语句就是对数组的只读操作!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-08-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档