我们可以用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
                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";