• C#中的迭代器


    迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象内部的表示。迭代器为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的借口。

    迭代器模式结构图:

    Iterator类

    复制代码
    /////////////////////////////////////////////////////////////  Iterator.cs //  Implementation of the Class Iterator //  Generated by Enterprise Architect //  Created on:      23-七月-2011 13:44:42 //  Original author: xinyuanzhang///////////////////////////////////////////////////////////
    namespace Test { ///<summary>/// 迭代抽象类 ///</summary>publicabstractclass Iterator {
    public Iterator() {
    }
    ~Iterator() {
    }
    publicvirtualvoid Dispose() {
    }
    publicabstractobject CurrentItem();
    publicabstractobject First();
    publicabstractbool IsDone();
    publicabstractobject Next();
    }
    //end Iterator}
    复制代码

    Aggregate聚集抽象类

    复制代码
    /////////////////////////////////////////////////////////////  Aggregate.cs //  Implementation of the Class Aggregate //  Generated by Enterprise Architect //  Created on:      23-七月-2011 13:46:01 //  Original author: xinyuanzhang///////////////////////////////////////////////////////////
    namespace Test { ///<summary>/// 聚集抽象类 ///</summary>publicabstractclass Aggregate {
    public Aggregate() {
    }
    ~Aggregate() {
    }
    publicvirtualvoid Dispose() {
    }
    publicabstract Iterator CreateIterator();
    }
    //end Aggregate}
    复制代码

    ConcreteIterato具体迭代器类

    复制代码
    /////////////////////////////////////////////////////////////  ConcreteIterator.cs //  Implementation of the Class ConcreteIterator //  Generated by Enterprise Architect //  Created on:      23-七月-2011 13:48:10 //  Original author: xinyuanzhang///////////////////////////////////////////////////////////
    namespace Test { publicclass ConcreteIterator : Iterator {
    //定义有一个具体聚集对象public ConcreteAggregate m_ConcreteAggregate; privateint current =0;
    public ConcreteIterator() { }
    //初始化聚集对象传入public ConcreteIterator(ConcreteAggregate aggregate) { this.m_ConcreteAggregate = aggregate; }
    ~ConcreteIterator() {
    }
    publicoverridevoid Dispose() {
    }
    ///<summary>/// 返回当前聚集对象 ///</summary>///<returns></returns>publicoverrideobject CurrentItem() {
    return m_ConcreteAggregate[current]; }
    ///<summary>/// 得到聚集的第一个对象 ///</summary>///<returns></returns>publicoverrideobject First() {
    return m_ConcreteAggregate[0]; }
    ///<summary>/// 判断当前是否遍历到结尾 ///</summary>///<returns></returns>publicoverridebool IsDone() {
    return current >= m_ConcreteAggregate.Count ?true : false; }
    ///<summary>/// 得到聚集的下一个对象 ///</summary>///<returns></returns>publicoverrideobject Next() {
    object ret =null; current++; if (current < m_ConcreteAggregate.Count) { ret = m_ConcreteAggregate[current]; } return ret; }
    }
    //end ConcreteIterator}
    复制代码

    ConcreteAggregate具体聚集类

    复制代码
    /////////////////////////////////////////////////////////////  ConcreteAggregate.cs //  Implementation of the Class ConcreteAggregate //  Generated by Enterprise Architect //  Created on:      23-七月-2011 13:49:53 //  Original author: xinyuanzhang///////////////////////////////////////////////////////////using System.Collections.Generic;
    namespace Test { publicclass ConcreteAggregate : Aggregate {
    public ConcreteAggregate() {
    }
    ~ConcreteAggregate() {
    }
    publicoverridevoid Dispose() {
    }
    publicoverride Iterator CreateIterator() {
    returnnew ConcreteIterator(this); }
    //声明一个IList<T>变量,用于存放聚合对象private IList<object> items =new List<object>();
    //返回集合总个数publicint Count { get { return items.Count; } }
    //声明一个索引器publicobjectthis[int index] { get { return items[index]; } set { items.Insert(index, value); } }
    }
    //end ConcreteAggregate}
    复制代码

    客户端代码

    复制代码
    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Common; using System.Data;
    namespace Test { class Program { staticvoid Main(string[] args) { ConcreteAggregate a =new ConcreteAggregate();
    a[
    0] ="A"; a[1] ="B"; a[2] ="C"; a[3] ="D"; a[4] ="E"; a[5] ="F"; a[6] ="G";
    Iterator i
    =new ConcreteIterator(a); object item = i.First(); while (!i.IsDone()) { Console.WriteLine(i.CurrentItem()); i.Next(); } Console.ReadKey(); } } }
    复制代码

    运行结果

    在实际使用中.NET框架已经准备好了相关接口,C#支持关键字foreach,允许我们遍历任何数组类型的内容。任何支持GetEnumerator()方法的类型都可以通过foreach结构进行运算。这个方法是由IEnumerable接口定义的。对象支持这种行为说明它们能够向调用方法提供自己包含的子项。

    //这个接口告知调用方法的子项可以枚举publicinterface IEnumerable {     IEnumerator GetIEnumerator(); }

    GetEnumerator()方法返回一个IEumerator的引用。这个接口提供了基础设施,调用方法可以用来移动IEnumerable兼容容器包含的内部对象:

    复制代码
    //这个接口允许调用方法获取一个容器的子项publicinterface IEnumerator {     bool MoveNext();//将光标的内部位置向前移动。object Currect{get;}//获取当前的项void Reset();//将光标重置到第一个成员前面}
    复制代码

    可以修改自定义类型使之支持这些接口,一个更简单的方法是Array和其它许多类型已经实现了这2个接口,可以简单的请求到Array,如下所示:

    复制代码
    using System; using System.Collections; using System.Linq; using System.Text;
    namespace Test { publicclass LetterSet:IEnumerable { private Letter[] letterArr =new Letter[7];
    public LetterSet() { letterArr[0] =new Letter(1,"A"); letterArr[1] =new Letter(2,"B"); letterArr[2] =new Letter(3,"C"); letterArr[3] =new Letter(4,"D"); letterArr[4] =new Letter(5,"E"); letterArr[5] =new Letter(6,"F"); letterArr[6] =new Letter(7,"G"); }
    public IEnumerator GetEnumerator() { return letterArr.GetEnumerator(); } } }
    复制代码

    客户端代码

    复制代码
    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Common; using System.Data;
    namespace Test { class Program { staticvoid Main(string[] args) { LetterSet ls =new LetterSet(); foreach (Letter l in ls) { Console.WriteLine(l.Name); }
    Console.ReadKey(); } } }
    复制代码

    上面还不是最简单的方法,从.Net2.0以后,可以通过迭代器来构建使用foreach的类型。

    简单来说,迭代器指定了容器内部项被foreach处理时该如何返回,虽然迭代器方法还是必须命名为GetEnumerator(),返回值还是IEumerator类型,但自定义类不需要实现原来那些接口了:

    复制代码
    using System; using System.Collections; using System.Linq; using System.Text;
    namespace Test { publicclass LetterSet { private Letter[] letterArr =new Letter[7];
    public LetterSet() { letterArr[0] =new Letter(1,"A"); letterArr[1] =new Letter(2,"B"); letterArr[2] =new Letter(3,"C"); letterArr[3] =new Letter(4,"D"); letterArr[4] =new Letter(5,"E"); letterArr[5] =new Letter(6,"F"); letterArr[6] =new Letter(7,"G"); }
    public IEnumerator GetEnumerator() { foreach (Letter l in letterArr) { yieldreturn l; } } } }
    复制代码

    例中上GetEnumerator()的实现使用内部foreach逻辑迭代每个项,使用yield返回语法后,当前位置被存储下来,下次调用迭代器会从这个位置开始执行。也可以不使用foreach关键字,下面的用法并不推荐,因为当实例增多时,GetEnumerator()就不会同步,但是该方法的运行结果可以帮助我们理解yield关键字。

    复制代码
         public IEnumerator GetEnumerator()         {             yieldreturn letterArr[0];             yieldreturn letterArr[1];             yieldreturn letterArr[2];             yieldreturn letterArr[3];             yieldreturn letterArr[6];             yieldreturn letterArr[5];             yieldreturn letterArr[4];         }
    复制代码

    运行结果如下:

    yield关键字可以和任何方法一起使用,这些方法也被称为“命名迭代器”,其独特之处在于可以接受参数。构建命名迭代器时,这些方法必须定义为返回IEnumerable类型,而不是IEumerator类型,下例显示了一个通过参数决定排列顺序的方法:

    复制代码
    public IEnumerable GetLetters(bool IsASC)         {             if (IsASC)             {                 foreach (Letter l in letterArr)                 {                     yieldreturn l;                 }             }             else             {                 for (int i = letterArr.Length; i !=0; i--)                 {                     yieldreturn letterArr[i -1];                 }             }         }
    复制代码

    客户端代码

    foreach (Letter l in ls.GetLetters(false))             {                 Console.WriteLine(l.Name);             }

    运行结果

    命名迭代器是很有用的结构,因为一个自定义容器可以定义多重方式来请求返回的集。

    出处:http://www.cnblogs.com/MeteorSeed/archive/2011/07/23/2098659.html

  • 相关阅读:
    js作用域
    正则表达式方法
    for-in
    关于this
    由indexOf引发的一系列探究和思考
    Html第一个程序
    转:1.ASP.Net MVC开发基础学习笔记;2.HtmlHelper与扩展方法
    转:单例模式
    转:ORM框架EF(Entity framework)实体框架
    C#lambda表达式
  • 原文地址:https://www.cnblogs.com/movemoon/p/2805262.html
Copyright © 2020-2023  润新知