C#迭代器(Foreach)实现方法

一、为非泛型列表创建迭代器块

using System;

using System.Collections.Generic;

using System.Text;

 

namespace ForeachConstruct

{

    /*

     * 下面的代码示例阐释如何编写可与foreach 一起使用的非泛型集合类。

     * 该类是字符串标记化拆分器,类似于C 运行时库函数strtok

     * 此示例描述的是只有在您无法使用泛型集合类时才采用的推荐做法。

     * C# 语言和.NET Framework 2.0 版和更高版本支持泛型。

     * 在下面的示例中,Tokens 使用“”“-”作为分隔符将句子“This is a sample sentence.-yang lei”

     * 拆分为标记,并使用foreach 语句枚举这些标记:

     */

 

    #region 省略接口

    /*

     * C# 中,集合类并非必须严格从IEnumerable IEnumerator 继承才能与foreach 兼容;

     * 只要类有所需的GetEnumeratorMoveNextReset Current 成员,便可以与foreach 一起使用。

     * 省略接口的好处为,使您可以将Current 的返回类型定义得比object 更明确,

     * 从而提供了类型安全。

     * 省略IEnumerable IEnumerator 的缺点是,

     * 集合类不再能够与其他公共语言运行库兼容语言的foreach 语句或等效项交互操作

     */

    /*

    public class Tokens

    {

        private string[] elements;

 

        public Tokens(string source, char[] delimiters)

        {

            elements = source.Split(delimiters);

        }

 

        #region IEnumerable 成员

 

 

        public TokenEnumerator GetEnumerator()

        {

            return new TokenEnumerator(this);

        }

        #endregion

 

        public class TokenEnumerator

        {

            private int position = -1;

            private Tokens t;

 

            public TokenEnumerator(Tokens t)

            {

                this.t = t;

            }

 

            #region IEnumerator 成员

 

            public string Current

            {

                get

                {

                    return t.elements[position];

                }

            }

 

            public bool MoveNext()

            {

                if (position < t.elements.Length - 1)

                {

                    position++;

                    return true;

                }

                else

                {

                    return false;

                }

            }

 

            public void Reset()

            {

                position = -1;

            }

 

            #endregion

        }

    }

    */

    #endregion

 

    #region 实现接口

    /*

     * 您可以同时拥有两者的优点,即C# 中的类型安全以及与其他公共语言运行库兼容语言的互操作性,

     * 方法是从IEnumerable IEnumerator 继承并使用显式接口实现。

     */

    public class Tokens : System.Collections.IEnumerable

    {

        private string[] elements;

 

        public Tokens(string source, char[] delimiters)

        {

            elements = source.Split(delimiters);

        }

 

        #region IEnumerable 成员

 

        public System.Collections.IEnumerator GetEnumerator()

        {

            return new TokenEnumerator(this);

        }

 

        #endregion

 

        public class TokenEnumerator : System.Collections.IEnumerator

        {

            private int position = -1;

            private Tokens t;

 

            public TokenEnumerator(Tokens t)

            {

                this.t = t;

            }

 

            #region IEnumerator 成员

 

            public object Current

            {

                get

                {

                    return t.elements[position];

                }

            }

 

            public bool MoveNext()

            {

                if (position < t.elements.Length - 1)

                {

                    position++;

                    return true;

                }

                else

                {

                    return false;

                }

            }

 

            public void Reset()

            {

                position = -1;

            }

 

            #endregion

        }

    }

    #endregion

 

    class Program

    {

        static void Main(string[] args)

        {

            Tokens f = new Tokens("This is a sample sentence.-yang lei", new char[] { ' ', '-' });

 

            foreach (string item in f)

            {

                System.Console.WriteLine(item);

            }

        }

    }

 

    /*

     * 输出

        This

        is

        a

        sample

        sentence.

        yang

        lei

        请按任意键继续. . .

     */

}

 

 

二、为泛型列表创建迭代器块 

using System;

using System.Collections.Generic;

using System.Text;

using System.Collections;

 

namespace ForeachConstruct

{

    //为泛型列表创建迭代器块

    public class Stack<T> : IEnumerable<T>

    {

        private T[] values = new T[100];

        private int top = 0;

 

        public void Push(T t)

        {

            values[top++] = t;

        }

 

        public T Pop()

        {

            return values[--top];

        }

 

        public IEnumerable<T> TopToBottom

        {

            get { return this; }

        }

 

        public IEnumerable<T> BottomToTop

        {

            get

            {

                for (int i = 0; i < top; i++)

                {

                    yield return values[i];

                }

            }

        }

 

        public IEnumerable<T> TopN(int n)

        {

            int j = (n >= top) ? 0 : top - n;

 

            for (int i = top; --i >= j; )

            {

                yield return values[i];

            }

        }

 

        #region IEnumerable<T> 成员

 

        public IEnumerator<T> GetEnumerator()

        {

            for (int i = top; --i >= 0; )

            {

                yield return values[i];

            }

        }

 

        #endregion

 

        #region IEnumerable 成员

 

        IEnumerator IEnumerable.GetEnumerator()

        {

            return GetEnumerator();

        }

 

        #endregion

    }

 

    class Test

    {

        static void Main()

        {

            Stack<int> s = new Stack<int>();

            for (int i = 0; i < 10; i++)

            {

                s.Push(i);

            }

 

            foreach (int n in s)

            {

                System.Console.Write("{0} ", n);

            }

            System.Console.WriteLine();

 

            foreach (int n in s.TopToBottom)

            {

                System.Console.Write("{0} ", n);

            }

            System.Console.WriteLine();

 

            foreach (int n in s.BottomToTop)

            {

                System.Console.Write("{0} ", n);

            }

            System.Console.WriteLine();

 

            foreach (int n in s.TopN(7))

            {

                System.Console.Write("{0} ", n);

            }

            System.Console.WriteLine();

        }

    }

 

    /*

     * 输出

        9 8 7 6 5 4 3 2 1 0

        9 8 7 6 5 4 3 2 1 0

        0 1 2 3 4 5 6 7 8 9

        9 8 7 6 5 4 3

        请按任意键继续. . .

     */

 

    /* yield的说明

     * 在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。它的形式为下列之一:

        yield return expression;

        yield break;

     *

        参数

        expression

        进行计算并以枚举数对象值的形式返回。expression 必须可以隐式转换为迭代器的yield 类型。

     *

        备注

        yield 语句只能出现在iterator 块中,该块可用作方法、运算符或访问器的体。

        这类方法、运算符或访问器的体受以下约束的控制:

        不允许不安全块。

        方法、运算符或访问器的参数不能是ref out

        yield 语句不能出现在匿名方法中。

        当和expression 一起使用时,yield return 语句不能出现在catch 块中或含有一个或多个catch 子句的try 块中。

     *

        包含yield语句的方法或属性称为迭代块。迭代块必须声明为返回IEnumeratorIEnumerable接口.

        yield语句从本质上讲是运用了延迟计算(Lazy evaluationdelayed evaluation)的思想。

        Wiki上可以找到延迟计算的解释:将计算延迟,直到需要这个计算的结果的时候才计算,

        这样就可以因为避免一些不必要的计算而改进性能,在合成一些表达式时候还可以避免一些不必要的条件,

        因为这个时候其他计算都已经完成了,所有的条件都已经明确了,有的根本不可达的条件可以不用管了。

     */

 

}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值