• 枚举器和迭代器


    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 迭代器实质:状态机
    
    
  • 相关阅读:
    Cocos2d-iphone 为sprite添加双击的事件响应
    经典书单 —— 语言/算法/机器学习/深度学习/AI/CV/PGM
    经典网络站点、论坛、博客
    经典网络站点、论坛、博客
    Python 格式化输出 —— 小数转化为百分数
    Python 格式化输出 —— 小数转化为百分数
    移位运算与除法、取模运算
    移位运算与除法、取模运算
    火箭、飞行器、探测器的发射
    火箭、飞行器、探测器的发射
  • 原文地址:https://www.cnblogs.com/rwh871212/p/6963413.html
Copyright © 2020-2023  润新知