yield迭代器

迭代器是使用在 foreach 中的集合。以前写过一篇《 小议foreach 》。在其中写了实现一个可以用于 foreach 的集合。在 C#2.0 中使用迭代器创建一个用于 foreach 的集合,实现上比较简单:继承于 IEumnerable ,并实现 GetEnumerator()

首先这个集合要基于IEnumerable(可以使用泛型),下面先来实现一个非泛型版的迭代器。代码如下(非泛型代码示例来源于MSDN):

public class DaysOfTheWeek : System.Collections.IEnumerable

        {

            string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };

 

            public System.Collections.IEnumerator GetEnumerator()

            {

                for (int i = 0; i < m_Days.Length; i++)

                {

                    yield return m_Days[i];

                }

            }

        }

 

        class TestDaysOfTheWeek

        {

            static void Main()

            {

                DaysOfTheWeek week = new DaysOfTheWeek();

                foreach (string day in week)

                {

                    System.Console.Write(day + " ");

                }

                Console.Read();

            }

      }

操作结果是:

Sun Mon Tue Wed Thr Fri Sat

其中yied return关键字产生枚举元素

 

泛型版迭代器的实现代码如下:

static void Main(string[] args)

        {          

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

            stack.items = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            foreach (int i in stack)

            {

                Console.WriteLine(i);

            }

            Console.Read();

     }

public class Stack<T> : IEnumerable<T>

    {

        public T[] items;

 

        public IEnumerator<T> GetEnumerator()

        {

            for (int i = 0; i < items.Length; i++)

            {

                yield return items[i];

            }

        }

 

        IEnumerator IEnumerable.GetEnumerator()

        {

            return GetEnumerator();

        }

}

运行结果如下:

1

2

3

4

5

6

7

8

9

10

其中G

在实现泛型迭代器时我一直没有写IEnumerator IEnumerable.GetEnumerator()这个方法,所以编译器一直在给我报错,(猜想)这个方法应该IEnumerator<T>接口中的一个抽象方法。而这个方法中调用的GetEnumerator(),通过集成环境中的提示发现,实际上是上面写到的IEnumerator<T> GetEnumerator()这个泛型方法。

 

在自定义迭代器时,我们可以利用yield break关键字跳出循环。如上面的例子中,我们想只输出小于等于5的项,调整上面代码,如:

public class Stack<T> : IEnumerable<T>

    {

        public T[] items;

 

        public IEnumerator<T> GetEnumerator()

        {

            for (int i = 0; i < items.Length; i++)

            {               

                if ((Convert.ToInt32(items[i]) > 5))

                    yield break;

                yield return items[i];

            }

        }

 

        IEnumerator IEnumerable.GetEnumerator()

        {

            return GetEnumerator();

        }

操作结果:

1

2

3

4

5

 

迭代器的机制:

     实际上迭代器只是在C#2.0中通过编译器一层额外处理的,用来简化创建可用于foreach的枚举集合的工作,从性能上没有什么变化。对于其生成的中间语言没有太多的变化。

 

你可能感兴趣的:(yield迭代器)