【迭代器模式在.NET中的应用】

 

迭代器模式

  定义参考 wiki: Iterator pattern

  迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访集合内部的数据。   ------- 节选自 《大话设计模式》P207 

  我们可以将迭代器模式抽离出几个重要组成部分:

  1. 迭代器抽象类

  2. 聚集抽象类

  3. 具体迭代器类

  4. 具体聚集类

 

1. 迭代器抽象类

 1 public interface IEnumerator
 2 {
 3         bool MoveNext();
 4     
 5         Object Current {
 6             get; 
 7         }
 8     
 9         void Reset();
10 }
View Code

reference: .NET IEnumerator

 

2. 聚集抽象类

1 public interface IEnumerable
2 {
3         IEnumerator GetEnumerator();
4 }
View Code

reference: .NET IEnumerable

 

3. 具体迭代器类

通过查看.NET代码可以知道,在List、Dictionary类中都声明了具体的迭代器struct Enumerator,List中Enumerator代码如下:

 1 [Serializable]
 2 public struct Enumerator : IEnumerator<T>,
 3 System.Collections.IEnumerator
 4 {
 5             private List<T> list;
 6             private int index;
 7             private int version;
 8             private T current;
 9  
10             internal Enumerator(List<T> list) {
11                 this.list = list;
12                 index = 0;
13                 version = list._version;
14                 current = default(T);
15             }
16  
17             public void Dispose() {
18             }
19  
20             public bool MoveNext() {
21  
22                 List<T> localList = list;
23  
24                 if (version == localList._version && ((uint)index < (uint)localList._size)) 
25                 {                                                     
26                     current = localList._items[index];                    
27                     index++;
28                     return true;
29                 }
30                 return MoveNextRare();
31             }
32  
33             private bool MoveNextRare()
34             {                
35                 if (version != list._version) {
36                     ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
37                 }
38  
39                 index = list._size + 1;
40                 current = default(T);
41                 return false;                
42             }
43  
44             public T Current {
45                 get {
46                     return current;
47                 }
48             }
49  
50             Object System.Collections.IEnumerator.Current {
51                 get {
52                     if( index == 0 || index == list._size + 1) {
53                          ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
54                     }
55                     return Current;
56                 }
57             }
58     
59             void System.Collections.IEnumerator.Reset() {
60                 if (version != list._version) {
61                     ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
62                 }
63                 
64                 index = 0;
65                 current = default(T);
66             }
67 }
View Code

reference: .NET List Enumerator

 

4. 具体聚集类

同样以List为例,reference: .NET List

 

5. 利用 foreach 来遍历对象

foreach(int i in obj) {...}经过编译器转换将会变成如下:

var tmp = obj.GetEnumerator();
int i;
while (tmp.MoveNext()) {
      i = tmp.Current;
          {...} // your code
}

所以可以知道,只要我们实现了迭代器类和聚集类,那么就可以通过foreach来进行遍历了。

 

参考

1. How do foreach loops work in C#?

2. Foreach On IEnumerable

3. 详解C# 迭代器

4. .Net学习难点讨论系列11 - foreach与迭代器

 

posted @ 2015-04-11 02:07  michael111  阅读(170)  评论(0编辑  收藏  举报