.net基础---迭代器

迭代器

迭代器是一种快速访问集合元素的方法,它通过封装记录当前访问到的集合元素的下标值(position),访问当前元素直接获取其中的当前值即可(当前值通过下标获取);访问下一元素时通过判断是否存在下一个元素,如果存在则通过moveNext方式,将当前访问的下标值往后移(+1)。

在.net中迭代器的实现主要就是foreach语法。能够使用foreach的语法的必须实现IEnumerable接口。IEnumerable定义GetEnumerator接口返回的IEnumerator,而IEmerator接口则是迭代的真正实现。

示例代码

 1     /// <summary>
 2     /// 可迭代类(集合,例如List)
 3     /// </summary>
 4     /// <typeparam name="T"></typeparam>
 5     public class CustomerEnumable<T> : IEnumerable<T>
 6     {
 7 
 8         private T[] _data;
 9         #region 集合本来的属性
10         public int Count => _data.Length;
11         /// <summary>
12         /// 索引器
13         /// </summary>
14         /// <param name="index"></param>
15         /// <returns></returns>
16         public T this[int index]
17         {
18             get { return _data[index]; }
19             set { _data[index] = value; }
20         }
21         //........
22        
23         public CustomerEnumable(T[] data)
24         {
25             this._data = data;
26         }
27         #endregion
28         /// <summary>
29         /// 获取非泛型迭代器
30         /// </summary>
31         /// <returns></returns>
32         public IEnumerator GetEnumerator()
33         {
34             return new CustomerEnumerator<T>(_data);
35         }
36         /// <summary>
37         /// 获取泛型迭代器
38         /// </summary>
39         /// <returns></returns>
40         IEnumerator<T> IEnumerable<T>.GetEnumerator()
41         {
42             return new CustomerEnumerator<T>(_data);
43         }
44     }
45     /// <summary>
46     /// CustomerEnumable的迭代器实现
47     /// </summary>
48     /// <typeparam name="T"></typeparam>
49     public class CustomerEnumerator<T> : IEnumerator<T>
50     {
51         private int _position = -1;
52         private T[] _data;
53         /// <summary>
54         /// 当前值
55         /// </summary>
56         public object Current => _data[_position];
57         /// <summary>
58         /// 当前值(泛型)
59         /// </summary>
60         T IEnumerator<T>.Current => _data[_position];
61 
62         public CustomerEnumerator(T[] data )
63         {
64             this._data = data;
65         }
66         public void Dispose()
67         {
68             this._data = null;
69         }
70         /// <summary>
71         /// 判断下一个元素是否存在,存在则将position加1,并返回true,否则返回false表示无下一个元素
72         /// </summary>
73         /// <returns></returns>
74         public bool MoveNext()
75         {
76             if (_position < _data.Length - 1)
77             {
78                 _position++;
79                 return true;
80             }
81             else
82             {
83                 return false;
84             }
85         }
86         /// <summary>
87         /// 重设
88         /// </summary>
89         public void Reset()
90         {
91             this._position = -1;
92         }
93     }

 

 

使用示例

 1             string[] brands = new string[] { "Red b", "Green g", "Yellow d", "Blue Z" };
 2             var brandList = new CustomerEnumable<string>(brands);
 3 
 4             
 5             //1、使用for遍历
 6             for (int i = 0; i < brandList.Count; i++)
 7             {
 8                 Console.WriteLine(brandList[i]);   
 9             }
10             //2、使用foreach语法
11             foreach (var brandItem in brandList)
12             {
13                 Console.WriteLine(brandItem);
14             }
15             //3、直接通过迭代器访问(其实就是foreach的实际实现) 
16             var brandEnumerator = brandList.GetEnumerator();//因为GetEnumerator方法每次都是返回新的迭代实现,所以无需手工调用Reset
17             while (brandEnumerator.MoveNext())
18             {
19                 Console.WriteLine(brandEnumerator.Current);
20             }

 

 

附:

1、foreach遍历集合比直接使用for要快?

这个是不一定的,因为通过了解迭代器的实现,我们可以知道它最终还是按照下标去顺序遍历的。而这些集合基本上都是内存连续的。当我们使用for也是按照下标顺序获取(不存在跳跃的情况下),其实性能是差不多的。

当然foreach语法比较简洁,不用我们去维护下标值,所以还是建议使用foreach的。

2、.net中yield关键字其实是一种语法糖,最终还是通过实现IEnumberable<T>、IEnumberable、IEnumberator<T>和IEnumberator接口实现的迭代功能(可以通过IL码查看其内部实现,此处略)。

简单示例

1         public IEnumerable<string> GetSubjectEnumerable()
2         {
3             yield return "C#";
4             yield return "Java";
5             yield return "Python";
6             yield return "Go";
7         }

 

1             foreach (var item in GetSubjectEnumerable())
2             {
3                 Console.WriteLine(item);
4             }

 

 

 

---------

以上就是对迭代器概念的回顾

posted on 2020-12-17 01:14  john_yong  阅读(210)  评论(0编辑  收藏  举报

导航