• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#枚举器:foreach语句、IEnumerable、IEnumerator以及yieldreturn(一) ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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;
    }
}

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#中父子窗口之间实现控件互操作发布时间:2022-07-18
下一篇:
C#中的委托和事件(详解)发布时间:2022-07-18
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap