C# 枚舉器


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 }

 

運行結果:

 

如果您看了本篇博客,覺得對您有所收獲,請點擊右下角的 [推薦]

如果您想轉載本博客,請注明出處

如果您對本文有意見或者建議,歡迎留言

感謝您的閱讀,請關注我的后續博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM