枚举器和迭代器

1、枚举器和可枚举类型
foreach语句可以循环一次取数组中元素的原理:数组可以提供一个枚举器Enumerator的对象,枚举器可以知道元素的次序。
获取一个对象枚举器的方法是调用对象的GetEnumerator方法。实现了GetEnumerator方法的类型叫做可枚举类型Enumerable。
2 IEnumerator接口
实现了IEnumerator接口的枚举器包含3个函数成员:Current、MoveNext以及ReSet
使用foreach语句其实程序内部运行的代码如下:
int[] MyArray = { 10,11,12,13};
            IEnumerator ie = MyArray.GetEnumerator();
            while (ie.MoveNext())
            {
                int i = (int)ie.Current;
                Console.WriteLine(i.ToString());
            }
一个使用IEnumerator和IEnumerable的例子:
 class ColorEnumerator : IEnumerator
    {
        string[] _colors;
        int _position = -1;
        public ColorEnumerator(string[] theColors)
        {
            _colors = newstring[theColors.Length];
            for (int i = 0; i < theColors.Length; i++)
                _colors[i] = theColors[i];
        }
        public object Current//实现IEnumerator接口的三个成员
        {
            get
            {
                if (_position == -1)
                    throw new InvalidOperationException();
                if (_position >= _colors.Length)
                    throw new InvalidOperationException();
                return _colors[_position];//返回的是object类型
            }
        }
        public bool MoveNext()
        {
            if (_position < _colors.Length - 1)
            {
                _position++;
                returntrue;
            }
            else
                returnfalse;
        }
        publicvoid Reset()
        {
            _position = -1;
        }
 
    }
    class Spectrum : IEnumerable//可枚举类Spectrum,它的枚举器是ColorEnumerator
    {
        string[] Colors = { "violet","blue","red","yellow","green"};
        public IEnumerator GetEnumerator()
        {
            return new ColorEnumerator(Colors);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Spectrum spectrum = new Spectrum();
            foreach (string color in spectrum)
            {
                Console.WriteLine(color);
            }
        }
    }
3 泛型枚举接口 IEnumerator<T> IEnumerable<T>
    publicclassColorEnumberatorList : IEnumerator<String>   实现一个泛型枚举器接口
    {
        string[] Colors;
        int Position = -1;
        publicstring Current// 当前元素 泛型 
        {
            get
            {
                return Colors[Position];
            }
        }
        objectIEnumerator.Current/// 显示实现Current 非泛型 
        {
            get { return Colors[Position]; }
        } 
        publicbool MoveNext() /// 移动到下一个 
        {
            if (Position < Colors.Length - 1)
            {
                Position++;
                returntrue;
            }
            else
            {
                returnfalse;
            }
        }
        publicvoid Reset() /// 重置 
        {
            Position = -1;
        }
        publicvoid Dispose()/// 销毁操作 
        {
        } 
        public ColorEnumberatorList(string[] theColors) /// 构造函数 
        {
            Colors = newstring[theColors.Length];
            for (int i = 0; i < theColors.Length; i++)
            {
                Colors[i] = theColors[i];
            }
        }
    }
    publicclass Spectrum : IEnumerable<string>    /// 泛型可枚举类 实现 
    {
        string[] Colors = { "Red", "Yellow", "Blue" };
        publicIEnumerator<string> GetEnumerator()  /// IEnumerable<T>版本" 
        {
            returnnewColorEnumberatorList(Colors);
        }
        IEnumeratorIEnumerable.GetEnumerator() /// 显示实现 IEnumerable版本 
        {
            returnnewColorEnumberatorList(Colors);
        }
    }
    class泛型枚举器接口
    {
        staticvoid Main(string[] args)
        {
            Spectrum spectrum = newSpectrum();
            foreach (string color in spectrum)// 循环遍历时,先调用GetEnumerator返回一个 ColorEnumberatorList 类型的枚举器
            {
                Console.WriteLine(color);
            }
        }
    }
泛型接口和非泛型接口的区别:
泛型接口:IEnumerable<T>接口的GetEnumerator方法返回实现IEnumerator<T>的枚举器的实例;实现IEnumerator<T>的类实现了Current属性,它返回实际类型的对象,而不是object基类的引用。
非泛型接口:IEnumerable接口的GetEnumerator方法返回实现IEnumerator的枚举器的实例;实现IEnumerator的类实现了Current属性,它返回object的引用,然后我们必须把它转换为实际类型的对象。
4 迭代器 
publicIEnumerator<string> BlackAndWhite()
        {
            yieldreturn"black";
            yieldreturn"gray";
            yieldreturn"white";
        }
若在第一个yield return返回,则不执行后面的。

4.1 迭代器的常见使用模式有两种:
(1)枚举器的迭代器模式 
//IEnumerator的迭代器模式:使用迭代器来返回IEnumerator
    classMyClass1////实现了GetEnumerator方法的类就拥有枚举器,拥有枚举器就是可枚举类型
    {
        publicIEnumerator<string> GetEnumerator()
        {
            return IteratorMethod();//直接调取使用迭代器生成枚举器的方法来返回枚举器
        } 
        privateIEnumerator<string> IteratorMethod()//迭代器这里是用来生成枚举器的
        {
            yieldreturn"black";
            yieldreturn"gray";
            yieldreturn"white";
        }
    }
(2)可枚举类型的迭代器模式
   //IEnumerable的迭代器模式:使用迭代器来返回IEnumerable
    classMyClass//实现了GetEnumerator方法的类就拥有枚举器,拥有枚举器就是可枚举类型
    {
        publicIEnumerator<string> GetEnumerator()
        {
            IEnumerable<string> myEnumerable = BlackAndWhite();//要实现GetEnumerator方法先要获取一个
                                                              //可枚举类型然后返回其枚举器
            return myEnumerable.GetEnumerator();
        }
        public  IEnumerable<string> BlackAndWhite()//迭代器这里就是用来产生可枚举类型的
        {
            yieldreturn"black";
            yieldreturn"gray";
            yieldreturn"white";
        }
    }
4.2 产生多个可枚举类型
 classSpectrumD//有两个方法返回可枚举类型  SpectrumD类本身不是可枚举类型不能foreach 因为没实现GetEnumerator()
    {
        string[] colors = { "violet", "blue", "red", "yellow", "green","orange","black" };
        publicIEnumerable<string> UVtoIR()
        {
            for (int i = 0; i < colors.Length; i++)
            {
                yieldreturn colors[i];
            }
        }
        publicIEnumerable<string> IRtoUV()
        {
            for (int i = colors.Length-1; i >=0 ; i--)
            {
                yieldreturn colors[i];
            }
        }
    }

4.3 将迭代器定义为属性
    classSpectrumA
    {
        bool _ListFromUVtoIR;
        string[] colors = { "violet", "blue", "red", "yellow", "green", "orange", "black" };
 
        public SpectrumA(bool listFromUVtoIR)
        {
            _ListFromUVtoIR = listFromUVtoIR;
        }
        publicIEnumerator<string> GetEnumerator()//实现SpectrumA为可枚举类型  根据bool变量返回枚举器
        {
            return _ListFromUVtoIR ? UVtoIR : IRtoUV;
        }
 
        publicIEnumerator<string> UVtoIR //使用两个属性来返回两个不同的枚举器
        {
            get
            {
                for (int i = 0; i < colors.Length; i++)
                {
                    yieldreturn colors[i];
                }
            }
        }
        publicIEnumerator<string> IRtoUV
        {
            get
            {
                for (int i = colors.Length - 1; i >= 0; i--)
                {
                    yieldreturn colors[i];
                }
            }
        }
4.4 迭代器实质:状态机

原文地址:https://www.cnblogs.com/rwh871212/p/6963413.html