C# 枚举器和迭代器


1、枚举器和可枚举类型

  为什么数组可以使用 foreach 来遍历自己的元素呢?原因是数组可以按需提供一个叫做枚举器(enumerator)的对象。获取对象枚举器的方法是通过调用对象的 GetEnumerator 方法。实现GetEnumerator 方法的类型叫做可枚举类型。

C# 枚举器和迭代器

 

   foreach 结构设计用来和可枚举类型一起使用,比如数组,它就会执行以下行为:

    -通过调用 GetEnumerator 方法获取对象的枚举器

    -从枚举器中请求每一项并且把它作为迭代变量(iteration variable),代码可以读取该变量但不可以改变。

C# 枚举器和迭代器

 

 2、IEnumerator 接口

  实现了 IEnumerator 接口的枚举器包含 3 个函数成员:Current、MoveNext 以及 Reset。

  Current 时返回序列中当前位置项的属性(只读,返回Object 的引用,所以可以返回任何类型的对象)

  MoveNext 是把枚举器位置前进到集合中下一项的方法(有效返回True,无效 False,初始位置在序列的第一项之前,所以在第一次使用 Current 之前要先调用 MoveNext )

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

  如此便可以得到与 foreach 方法相近的方法:

1       int[] arr1 = { 10, 11, 12, 13 };                         // Create an array.
2 
3       IEnumerator ie = arr1.GetEnumerator();    //获取并存储枚举器
4 
5       while (ie.MoveNext())
6       {
7          int item = (int)ie.Current;        //获取当前项
8          Console.WriteLine($"Item value: { item }");           // Write it out.
9       }

 

3、IEnumerable 接口

  可枚举类是指实现了 IEnumerable 接口的类。此接口只有一个成员——GetEnumerator 方法

    public IEbumerator GetEnumerator{ … }

  自己实现可枚举类:

    实现 IEnumerator 接口的枚举器(实现 Current、MoveNext 和 Reset 方法)

    实现 IEnumerable 接口的枚举类(实现 GetEnumerator 方法)

    实现对应的方法是重点

 

4、泛型枚举接口

C# 枚举器和迭代器

 

   非泛型接口的实现是类型不安全的,它返回的是Object的引用,然后再转化为实际类型;泛型接口的枚举器是类型安全的,它返回实际类型的引用。

 

5、迭代器

  yield return 指定序列中要返回的下一项

  yield return 指定在序列中没有其他项
C# 枚举器和迭代器

 

 根据指定的返回类型,可以让迭代器产生枚举器或可枚举类型
 

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             MyClass mc = new MyClass();
 6             foreach (string shade in mc)
 7                 Console.Write($"{shade}  ");
 8 
 9             foreach (string shade in mc.BlackAndWhite())
10                 Console.Write($"{shade}  ");
11         }
12     }
13     class MyClass
14     {  
15 
16         public IEnumerator<string> GetEnumerator()
17         {
18             IEnumerable<string> myEnumerable = BlackAndWhite();
19             return myEnumerable.GetEnumerator();
20         }
21         public IEnumerable<string> BlackAndWhite()
22         {
23             yield return "black";
24             yield return "gray";
25             yield return "white";
26         }
27     }

   当我们实现返回枚举器的迭代器时,必须通过GetEnumertor方法来让类可枚举,它返回由迭代器返回的枚举器。
  如果我们在类中实现迭代器返回可枚举类型,我们可以让类实现GetEnumerator来让类本身可被枚举,或者不实现GetEnumerator,让类不可枚举,只需要直接调用迭代器方法进行foreach枚举。
 

6、创建多个可枚举类型

 1 class Spectrum
 2 {
 3    string[] colors = { "violet", "blue", "cyan", "green", "yellow", "orange", "red" };
 4 
 5    public IEnumerable<string> UVtoIR()
 6    {
 7       for (int i = 0; i < colors.Length; i++)
 8          yield return colors[i];
 9    }
10 
11    public IEnumerable<string> IRtoUV()
12    {
13       for (int i = colors.Length - 1; i >= 0; i--)
14          yield return colors[i];
15    }
16 }
17 
18 class Program
19 {
20    static void Main()
21    {
22       Spectrum spectrum = new Spectrum();
23 
24       foreach (string color in spectrum.UVtoIR())
25          Console.Write($"{ color } ");
26       Console.WriteLine();
27 
28       foreach (string color in spectrum.IRtoUV())
29          Console.Write($"{ color } ");
30       Console.WriteLine();
31    }
32 }

 

7、创建多个枚举器,并把迭代器作为属性

 1 using System;
 2 using System.Collections.Generic;
 3 class Spectrum
 4 {
 5    bool _listFromUVtoIR;
 6    string[] colors = { "violet", "blue", "cyan", "green", "yellow", "orange", "red" };
 7 
 8    public Spectrum(bool listFromUVtoIR)
 9    {
10       _listFromUVtoIR = listFromUVtoIR;
11    }
12 
13    public IEnumerator<string> GetEnumerator()
14    {
15       return _listFromUVtoIR
16       ? UVtoIR
17       : IRtoUV;
18    }
19 
20    public IEnumerator<string> UVtoIR
21    {
22       get
23       {
24          for (int i = 0; i < colors.Length; i++)
25             yield return colors[i];
26       }
27    }
28 
29    public IEnumerator<string> IRtoUV
30    {
31       get
32       {
33          for (int i = colors.Length - 1; i >= 0; i--)
34             yield return colors[i];
35       }
36    }
37 }
38 
39 class Program
40 {
41    static void Main()
42    {
43       Spectrum startUV = new Spectrum(true);
44       Spectrum startIR = new Spectrum(false);
45 
46       foreach (string color in startUV)
47          Console.Write($"{ color } ");
48       Console.WriteLine();
49 
50       foreach (string color in startIR)
51          Console.Write($"{ color } ");
52       Console.WriteLine();
53    }
54 }

 

 
 

原创文章,作者:506227337,如若转载,请注明出处:https://blog.ytso.com/273101.html

(0)
上一篇 2022年7月10日
下一篇 2022年7月10日

相关推荐

发表回复

登录后才能评论