C#知识点-枚举器和迭代器

Posted Kimisme

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#知识点-枚举器和迭代器相关的知识,希望对你有一定的参考价值。

一、几个基本概念的理解

问题一:为什么数组可以使用foreach输出各元素

答:数组是可枚举类型,它实现了一个枚举器(enumerator)对象;枚举器知道各元素的次序并跟踪它们的位置,然后返回请求的当前项

问题二:不用foreach能不能遍历各元素

image

问题三:什么是可枚举类

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

问题四:什么是枚举器

答:实现了IEnumerator接口的枚举器包含三个函数成员:Current,MoveNext,Reset

Current是只读属性,它返回object类型的引用;

MoveNext是把枚举器位置前进到集合的下一项的方法,它返回布尔值,指示新的位置是否有效位置还是已经超过了序列的尾部;

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

二、下面代码展示了一个可枚举类的完整示例

  1 namespace ConsoleApplication4
  2 {
  3     /// <summary>
  4     /// 自定义一个枚举对象
  5     /// </summary>
  6     class ColorEnumerator : IEnumerator
  7     {
  8         private string[] _colors;
  9         private int _position = -1;
 10 
 11         public ColorEnumerator(string[] arr)
 12         {
 13             _colors = arr;
 14             for (int i = 0; i < arr.Length; i++)
 15             {
 16                 _colors[i] = arr[i];
 17             }
 18         }
 19         public object Current
 20         {
 21             get
 22             {
 23                 if (_position == -1)
 24                 {
 25                     throw new InvalidOperationException();
 26                 }
 27                 if (_position >= _colors.Length)
 28                 {
 29                     throw new InvalidOperationException();
 30                 }
 31                 return _colors[_position];
 32             }
 33         }
 34 
 35         public bool MoveNext()
 36         {
 37             if (_position < _colors.Length - 1)
 38             {
 39                 _position++;
 40                 return true;
 41             }
 42             else
 43             {
 44                 return false;
 45             }
 46         }
 47 
 48         public void Reset()
 49         {
 50             _position = -1;
 51         }
 52     }
 53 
 54     /// <summary>
 55     /// 创建一个实现IEnumerable接口的枚举类
 56     /// </summary>
 57     class Spectrum : IEnumerable
 58     {
 59         private string[] Colors = { "red", "yellow", "blue" };
 60         public IEnumerator GetEnumerator()
 61         {
 62             return new ColorEnumerator(Colors);
 63         }
 64     }
 65 
 66     class Program
 67     {
 68         static void Main(string[] args)
 69         {
 70             Spectrum spectrum = new Spectrum();
 71             foreach (string color in spectrum)
 72             {
 73                 Console.WriteLine(color);
 74             }
 75             Console.ReadKey();
 76         }
 77     }
 78 }
 79 
View Code

三、泛型枚举接口

IEnumerable<T>接口的GetEnumerator方法返回实现IEnumerator<T>的枚举类的实例;

实现IEnumerator<T>的类实现了Current属性,它返回实际类型的对象,而不是object基类的引用;

所以非泛型接口的实现不是类型安全的,因为还需要转换为实际类型。

四、迭代器

1.使用迭代器来创建枚举器

  1 namespace ConsoleApplication5
  2 {
  3     class MyClass
  4     {
  5         /// <summary>
  6         /// 获取一个迭代器
  7         /// </summary>
  8         /// <returns></returns>
  9         public IEnumerator<string> GetEnumerator()
 10         {
 11             return ColorEnumerator();
 12         }
 13         /// <summary>
 14         /// 迭代器
 15         /// </summary>
 16         /// <returns></returns>
 17         public IEnumerator<string> ColorEnumerator()
 18         {
 19             yield return "red";
 20             yield return "yellow";
 21             yield return "blue";
 22         } 
 23     }
 24     class Program
 25     {
 26         static void Main(string[] args)
 27         {
 28             MyClass mc = new MyClass();
 29             foreach (string color in mc)
 30             {
 31                 Console.WriteLine(color);
 32             }
 33             Console.ReadKey();
 34         }
 35     }
 36 }
View Code

2.使用迭代器来创建枚举类型

  1 namespace ConsoleApplication6
  2 {
  3     class MyClass
  4     {
  5         public IEnumerator<string> GetEnumerator()
  6         {
  7             //获取可枚举类型
  8             IEnumerable<string> enumerable = ColorEnumerable();
  9             //获取枚举器
 10             return ColorEnumerable().GetEnumerator();
 11         }
 12 
 13         public IEnumerable<string> ColorEnumerable()
 14         {
 15             yield return "red";
 16             yield return "yellow";
 17             yield return "blue";
 18         } 
 19     }
 20     class Program
 21     {
 22         static void Main(string[] args)
 23         {
 24             MyClass mc = new MyClass();
 25             //使用类对象
 26             foreach (string color in mc)
 27             {
 28                 Console.WriteLine(color);
 29             }
 30             Console.WriteLine("-----------------------");
 31             //使用类枚举器的方法
 32             foreach (string color in mc.ColorEnumerable())
 33             {
 34                 Console.WriteLine(color);
 35             }
 36             Console.ReadKey();
 37         }
 38     }
 39 }
View Code

3.产生多个可迭代类型

  1 namespace ConsoleApplication7
  2 {
  3     class MyClass
  4     {
  5         private string[] Colors = { "red", "yellow", "blue" };
  6         //顺序
  7         public IEnumerable<string> ColorOrder()
  8         {
  9             for (int i = 0; i < Colors.Length; i++)
 10             {
 11                 yield return Colors[i];
 12             }
 13         }
 14         //逆序
 15         public IEnumerable<string> ColorReversed()
 16         {
 17             for (int i = Colors.Length - 1; i >= 0; i--)
 18             {
 19                 yield return Colors[i];
 20             }
 21         }
 22     }
 23     class Program
 24     {
 25         static void Main(string[] args)
 26         {
 27             MyClass mc = new MyClass();
 28             foreach (string color in mc.ColorOrder())
 29             {
 30                 Console.WriteLine(color);
 31             }
 32             Console.WriteLine("------------------");
 33             foreach (string color in mc.ColorReversed())
 34             {
 35                 Console.WriteLine(color);
 36             }
 37             Console.ReadKey();
 38         }
 39     }
 40 }
 41 
View Code

以上是关于C#知识点-枚举器和迭代器的主要内容,如果未能解决你的问题,请参考以下文章

C# 学习之路(十八)

Python迭代器和生成器的个人理解,再讲一讲协程

Python核心深入理解迭代器和生成器

理解迭代器和可迭代对象

枚举器和迭代器

枚举器和迭代器