1:枚举器和可枚举类型
我们知道使用foreach可以遍历数组中的元素。那么为什么数组可以被foreach语句处理呢,下面我们就进行讨论一下这个问题。
2:使用foreach语句
我们知道当我们使用foreach语句的时候,这个语句为我们依次取出了数组中的每一个元素。
例如下面的代码:
1 int[] arr = { 1, 2, 3, 4, 5, 6 };
2 foreach( int arry in arr )
3 {
4 Console.WriteLine("Array Value::{0}",arry);
5 }
输出效果为
为什么数组可以使用foreach来遍历,原因是数组可以按需提供一个叫做枚举器(enumerator)的对象,枚举器可以依次返回请求的数组中的元素,枚举器知道项的次序并且跟踪它在序列中的位置。依次返回请求的当前项。
对于有枚举器的类型而言,必须有一个方法来获取它这个类型。获取一个对象枚举器的方法是调用对象的GetEnumrator方法,实现GetEnumrator方法的类型叫做可枚举类型。那么数组就是可枚举类型。
下图演示一下可枚举类型和枚举器之间的关系。
foreach结构设计用来和可枚举类型一起使用,只要给它的遍历对象是可枚举类型,比如数组。
1:通过调用GetEnumrator方法获取对象的枚举器。
2:从枚举器中请求每一项并且把它作为迭代器,代码可以读取该变量,但不可以改变
foreach(Type VarName in EnumrableObject )
{
...
}
EnumrableObjec必须是可枚举类型。
2:IEnumrator接口
IEnumrator接口包含了3个函数成员:Current、MoveNext以及Reset;
.Current是返回序列中当前位置项的属性。(注意:Current它是只读属性,它返回Object类型的引用,所以可以返回任意类型)
.MoveNext是把枚举器位置前进到集合中下一项的方法。它也但会布尔值,指示新的位置是否是有效位置。
注:如果返回的位置是有效的,方法返回true;
如果新的位置是无效的,方法返回false;
枚举器的原始位置在序列中的第一项之前,因此MoveNext必须在第一次使用Current之前调用。
.Reset是把位置重置为原始状态的方法。
下面我们用图表示一下他们之间的关系
有了集合的枚举器,我们就可以使用MoveNext和Current成员来模仿foreach循环遍历集合中的项,例如,我们已经知道数组是可枚举类型,所以下面的代码手动做foreach语句
自动做的事情。
代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using System.Collections;
7
8 namespace ConsoleApplication1
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 int[] arr = { 1, 2, 3, 4, 5, 6 };
15 IEnumerator ie = arr.GetEnumerator();
16 while( ie.MoveNext() )
17 {
18 int i = (int)ie.Current;
19 Console.WriteLine("{0}", i);
20 }
21 }
22 }
23 }
程序运行的结果为
我们来用图解释一下代码中的数组结构
IEnumerable接口
数组是可枚举类型,是因为实现了IEnumerable接口的类,所以可枚举类都是因为实现了IEnumerable接口的类。
IEnumerable接口只有一个成员——GetEnumerator()方法,它返回对象的枚举器。
如图所示:
下面我们举一个使用IEnumerator和IEnumerable的例子
下面的代码展示了一个可枚举类的完整示例,该类叫Component(球形)。它的枚举器类为Shape(形状)。
代码如下:
1 using System;
2 using System.Collections;
3
4 namespace ConsoleApplication1
5 {
6 class Shape : IEnumerator
7 {
8 string[] _Shapes;
9 int _Position = -1;
10
11 public Shape(string[] _theShapes)
12 {
13 _Shapes = new string[_theShapes.Length];
14 for( int i = 0; i < _theShapes.Length; i++ )
15 {
16 _Shapes[i] = _theShapes[i];
17 }
18 }
19
20 public Object Current
21 {
22 get
23 {
24 if ( _Position == -1 )
25 throw new InvalidOperationException();
26 if (_Position >= _Shapes.Length)
27 throw new InvalidOperationException();
28 return _Shapes[_Position];
29 }
30 }
31
32 public bool MoveNext()
33 {
34 if (_Position < _Shapes.Length - 1)
35 {
36 _Position++;
37 return true;
38 }
39 else
40 return false;
41 }
42
43 public void Reset()
44 {
45 _Position = -1;
46 }
47 }
48
49 class Component : IEnumerable
50 {
51 string[] shapes = { "Circular", "spherical", "Quadrilateral", "Label" };
52 public IEnumerator GetEnumerator()
53 {
54 return new Shape( shapes );
55 }
56 }
57
58 class Program
59 {
60 static void Main(string[] args)
61 {
62 Component comp = new Component();
63 foreach ( string oshape in comp )
64 Console.WriteLine(oshape);
65 }
66
67 }
68 }
运行结果:
本文转载自: https://www.cnblogs.com/cxq0017/p/5844096.html