zoukankan      html  css  js  c++  java
  • C#枚举器:foreach语句、IEnumerable、IEnumerator以及yield return (一)

    using System;
    using System.Collections;

    C#中,我们通常可以用foreach语句来遍历数组或集合,下面深入探讨一下其工作原理 

    ①自定义集合MyList

        为了说明使用IEnumerable和IEnumerator接口,从而让数组或集合支持foreach语句的原理,我们首先自定义一个简单的链表形集合MyList,其中仅实现了AddData方法,其他相关方法没有写出,代码如下:

    //集合包含的项,即所谓的节点
    public class DataItem
    {
        public DataItem Next { get; set; }
        public object Data { get; set; }
        public DataItem(object data)
        {
            this.Data = data;
        }
    }
    //自定义集合类
    public class MyList
    {
        public DataItem FirstItem { get; set; }
        public DataItem LastItem { get; set; }
    
        public void AddData(object data)
        {
            DataItem newItem = new DataItem(data);
            if (this.FirstItem == null)
            {
                this.FirstItem = newItem;
                this.LastItem = newItem;
            }
            else
            {
                this.LastItem.Next = newItem;
                this.LastItem = newItem;
            }
        }
    }

    ②IEnumerable接口

        foreach在遍历集合的时候,实质上调用的是GetEnumerator方法,因此要使得集合支持foreach遍历,必须实现GetEnumerator方法,该方法定义在IEnumerable接口中,该接口定义如下:

    public interface IEnumerable
    {
        IEnumerator GetEnumerator();
    }

        

    ③IEmunerator接口

        因此只要让MyList继承IEnumerable接口,并实现GetEnumerator方法即可,可是该方法要求返回一个IEnumerator,现在我们还没任何地方实现这个IEmunerator接口,因此我们先来看看他的定义

    public interface IEnumerator
    {
         //集合中的当前元素。
        object Current { get; }
     
        //如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false。
        bool MoveNext();
     
        //将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
        void Reset();
    }

       

    ④实现IEnumerator接口

         从该接口的定义可以看出,foreach语句就是根据MoveNext方法和Current属性,一个一个遍历集合元素的,为了使得思路清晰,这里我们单独编写一个类来实现该接口,且该类会以上面的MyList为基础,以便MyList调用它

    public class MyEnumerator:IEnumerator
    {
        private DataItem currentItem = new DataItem(null);
        public MyEnumerator (MyList list) //使用MyList的实例来构造该类
        {
            this.currentItem.Next = list.FirstItem;
        }
        public object Current
        {
            get { return currentItem.Data; }
        }
        public bool MoveNext()
        {
            if(currentItem.Next != null)
            {
                currentItem = currentItem.Next;
                return true;
            }
            else
            {
                return false;
            }
        }
        public void Reset()
        {
            throw new NotImplementedException();
        }
    }

       

    ⑤实现IEnumerable接口

        有了这个MyEnumerator后,就可以让MyList实现IEnumerable接口中的GetEnumerator方法了,向MyList中添加如下代码

    public IEnumerator GetEnumerator()
    {
        return new MyEnumerator(this);
    }

       到此为止,虽然MyList的功能还十分不完善,但已经支持foreach语句遍历了,需要说明一点的是,不论MyList是否继承接口IEnumerable,只要实现了GetEnumerator方法,就可以支持foreach语句。

    ⑥yield return

        上面整个过程对于演示foreach语句的原理相当有用,不过每次都这样去实现就太费劲了,C#中可以使用yield return语句来帮我们自动实现IEnumerator接口,一下使得工作轻松多了,对MyList中的GetEnumerator方法作如下修改即可抛弃繁琐的MyEnumerator了

    public IEnumerator GetEnumerator()
    {
        //return new MyEnumerator(this);
        DataItem curent = this.FirstItem;
        while(curent != null)
        {
            yield return curent.Data;
            curent = curent.Next;
        }
    }
  • 相关阅读:
    《Go并发编程实战》读书笔记-初识Go语言
    使用Nexus配置Maven私有仓库
    Maven 本地资源库配置
    Django 2.2.x版本的ORM API实战案例
    在Mac OS环境下安装MySQL服务
    Pycharm搭建Django开发环境
    Hadoop生态圈-单点登录框架之CAS(Central Authentication Service)部署
    Ambari集成Kerberos报错汇总
    Hadoop生态圈-开启Ambari的Kerberos安全选项
    Hortonworks官网文档怎么找?
  • 原文地址:https://www.cnblogs.com/ArtofDesign/p/3612492.html
Copyright © 2011-2022 走看看