• .Net编程接口中的迭代器(转)


     

            给大家讲讲用于枚举元素集合的两个接口IEnumerator和IEnumerable。IEnumerator用于实现一个迭代器(相当于以前C++的文章中所说的iterator),它具备列举一个数据结构中所有元素所需要的一些方法和属性。而IEnumerable接口则用于返回一个迭代器对象,一个实现了IEnumerable的类型表示这个类型对象是可以枚举的。
        下面我们先来看看这两个接口的定义吧!

    IEnumerator

         迭代器用于枚举一个数据结构中的所有元素。

                
    namespace System.Collections
    {
    [ComVisible(true)]
    [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
    public interface IEnumerable
    {
    [DispId(-4)]
    IEnumerator GetEnumerator();
    }
    }
       从上面的定义我们可以看到,一个Emurator具备了枚举一个数据结构中所有元素的最基本能力:
       获取当前元素的的能力:Current属性;
       移动元素指针的能力:MoveNext方法; 
       重置迭代器的能力:Reset方法。
       这里的Current属性是Object类型,也就是可以返回所有类型元素,而与之对应的泛型接口是:System.Collections.Generic.IEnumerator<T>,它除了继承了Ienumerator之外,还增加了一个特定类型的Current属性。
    IEnumerable 
       IEnumerable声明一个类型为可枚举的类型,而它的定义很简单,就是返回一个迭代器。
    namespace System.Collections 
    {
    [ComVisible(true)]
    [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
        我们应该对C#风格的遍历语法应该很熟悉了,也就是foreach语句。说到foreach这个东西,其实在C++中也存在,但是是以函数的形式做在库里面的,而对C#来说,它已经被做到语言中去了。在绝大多数情形下,我们应该尽量使用foreach语句来遍历一个集合对象,而不是自己写一个for循环或者其他的while循环等,理由很简单:效率。而foreach语法需要被枚举的对象类型实现了IEnumerable接口。
        与IEnumerable对应的泛型接口是:System.Collections.Generic.IEnumerable<T>。
    设计一个集合类

        通常,IEnumerator和IEnumerable是一起使用的。假设我们设计一个属于自己的一个数据结构类MyCollection,并且让他可以被枚举,那么整体上应该怎么设计呢?我们看看下面的代码。
    class MyCollection:IEnumerable 
    {
    public struct MyEmurator : IEnumerator
    {
    //此处省略实现代码
    }
    //此处省略部分实现代码
    public IEnumerator GetEnumerator()
    {
    return new MyEmurator(this);
    }
    }
       这是一个典型的对IEnumerator和IEnumerable的应用方式。几乎所有的System.Collection里面的容器都是都是这样来设计的。将容器类型本身实现IEnumerable,表明容器是可枚举的。而迭代器类型则是一个嵌套类型,通过容器类的接口函数GetEnumerator来返回迭代器的实例。通常一个容器和它的迭代器是紧密相关的,并且一个容器配备一个迭代器已经足以,那么将迭代器定义为嵌套类型,避免了管理的混乱。

    实现一个2D List类型

        我们这里说的二维List类型,其实就是实现一个以List为元素的List,简而言之,这个List2D就是用来存放List的一个List;但是我们枚举的时候,并不想要枚举List2D里面的list, 而是想直接枚举list里面的元素。
        我们这里定义了一个泛型类List2D<T> ,实现了IEnumerable<T>接口。这里为了精简代码,这里没有让List2D实现IList接口,只提供了Add、Clear等几个简单方法。不多说了,还是来看看下面的代码吧!
    class List2D<T> : IEnumerable<T> 
    {
    //内嵌迭代器类型
    public struct Emurator : IEnumerator<T>
    {
    //此处代码先不写出
    }
    private List<List<T>> _lists=new List<List<T>>();//存储列表

    public List<T> this[int index]
    {
    get { return _lists[index]; }
    }

    public int Count
    {
    get
    {
    int count = 0;
    foreach (List<T> list in _lists)
    {
    count += list.Count;
    }
    return count;
    }
    }

    public void Add(List<T> item)
    {
    _lists.Add(item);
    }

    public void Clear()
    {
    _lists.Clear();
    }

    #region IEnumerable Members

    public IEnumerator GetEnumerator()
    {
    return ((IEnumerable<T>)this).GetEnumerator();
    }
    #endregion

    #region IEnumerable<T> Members

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
    return new Emurator(this);
    }
    #endregion
    }
  • 相关阅读:
    第07组 Beta冲刺(3/5)
    第07组 Beta冲刺(2/5)
    第07组 Beta冲刺(1/5)
    第07组 Alpha事后诸葛亮
    第07组 Alpha冲刺(6/6)
    第07组 Alpha冲刺(5/6)
    【置顶】CSP/NOIP 2020 (高二游记)
    【置顶】CSP/S 2019退役祭
    【置顶】一些关于停课的感想(随时更新,连着前一篇博客)11/11~11/15
    【置顶】我的2018~2019信息学之路
  • 原文地址:https://www.cnblogs.com/ejiyuan/p/1276918.html
Copyright © 2020-2023  润新知