C# 枚举器和迭代器

foreach语句

我们可以用foreach语句来遍历数组中的每一个元素。

为什么数组可以这么做,是因为数组提供了叫做 枚举器的对象

获取一个对象的枚举器方法是 调用对象的GetEnumerator方法,那么如果实现了这个方法的类型叫做 可枚举类型

 IEnumerator接口

实现IEnumerator接口的枚举器有三个函数成员

Current是返回序列中当前位置项的属性

MoveNext把枚举器前进到下一项的方法

  • 新的位置有效 返回true
  • 新的位置无效 返回false
  • 起始的位置在第一项之前,所有得在第一次使用Current之前调用

Reset是把位置重置为原始状态的方法

所以知道了枚举器,就可以模仿foreach循环遍历集合中的项

IEnumerable接口

可吗,枚举类是实现了IEnumerable接口的类,IEnumerable接口只有一个成员:GetEnumerator方法,它返回对象的枚举器

代码演示如下:

使用IEnumerator和IEnumerable

代码中展示了一个可枚举类:Spectrum,枚举器类为Color_Enumerator

using System;
using System.Collections;
using System.Linq;

namespace ConsoleApp3
{
    class ColorEnumerator : IEnumerator
    {
        private string[] _colors;
        private int _position = -1;

        public ColorEnumerator(string[] theColors)
        {
            _colors = new string[theColors.Length];
            for (int i = 0; i < theColors.Length; i++)
            {
                _colors[i] = theColors[i];
            }
        }

        public object Current
        {
            get
            {
                if(_position == -1)
                {
                    throw new InvalidOperationException();
                }

                if (_position >= _colors.Length)
                {
                    throw new InvalidOperationException();
                }

                return _colors[_position];
            }
        }

        public bool MoveNext()
        {
            if (_position < _colors.Length - 1)
            {
                _position++;
                return true;
            }

            return false;
        }

        public void Reset()
        {
            _position = -1;
        }
    }

    class Spectrum : IEnumerable
    {
        private string[] Colors = {"violet", "blue", "cyan", "green", "yellow", "orange", "red"};

        public IEnumerator GetEnumerator()
        {
            return  new ColorEnumerator(Colors);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Spectrum spectrum = new Spectrum();
            foreach (var color in spectrum)
            {
                Console.WriteLine(color);
            }
        }
    }
}

迭代器

C#提供了更简单的创建枚举器和可枚举类型的方式

//第一个代码
public
IEnumerator<string> BlackAndWhite() { yield return "black"; yield return "gray"; yield return "white"; }
//第二个代码
public IEnumerator<string> BlackAndWhite() { string[] theColors = {"black", "gray", "white"}; for (int i = 0; i < theColors.Length; i++) { yield return theColors[i]; } }

迭代器块是有一个或多个yield语句的代码块

它可以是:

方法主体,访问器主体,运算符主体

  • yield return语句指定了序列中返回的下一项
  • yield break语句指定了在序列中没有其他项

使用迭代器创建枚举器

 BlackAndWhite方法是一个迭代器块,可以为MyClass类产生返回枚举器的方法

MyClass还实现了GetEnumerator方法,调用了BlackAndWhite并且返回BlackAndWhite返回的枚举器

class MyClass
{
    public IEnumerator<string> GetEnumerator()
    {
        return BlackAndWhite();
    }

    public IEnumerator<string> BlackAndWhite()
    {
        yield return "black";
        yield return "gray";
        yield return "white";
    }
}

使用迭代器创建可枚举类型

public IEnumerator<string> GetEnumerator()
{
    IEnumerable<string> myEnumerable = BlackAndWhite();//获取可枚举类型
    return myEnumerable.GetEnumerator();//获取枚举器
}

public IEnumerable<string> BlackAndWhite()
{
    yield return "black";
    yield return "gray";
    yield return "white";
}

 

posted @ 2018-09-11 16:20  樱花落舞  阅读(827)  评论(1编辑  收藏  举报