IEnumerator和IEnumerable详解

https://www.cnblogs.com/cjm123/p/8671783.html


5

代码达到了遍历效果,但是在用foreach遍历时,IEnumerator和IEnumerable究竟是如何运行的,我们可以通过增加增加日志可以直观的看到原因。

//一个常量的数组,用于foreach遍历
class ConstArrayList : IEnumerable { public int[] constItems = new int[] { 1, 2, 3, 4, 5 }; public IEnumerator GetEnumerator() { WriteLine("GetIEnumerator"); return new ConstArrayListEnumeratorSimple(this); } } //这个常量数组的迭代器 class ConstArrayListEnumeratorSimple : IEnumerator { ConstArrayList list; int index; int currentElement; public ConstArrayListEnumeratorSimple(ConstArrayList _list) { list = _list; index = -1; } public object Current { get { WriteLine("Current"); return currentElement; } } public bool MoveNext() { if(index < list.constItems.Length - 1) { WriteLine("MoveNext true"); currentElement = list.constItems[++index]; return true; } else { WriteLine("MoveNext false"); currentElement = -1; return false; } } public void Reset() { WriteLine("Reset"); index = -1; } } class Program { static void Main(string[] args) { ConstArrayList constArrayList = new ConstArrayList(); foreach(int item in constArrayList) { WriteLine(item); } ReadKey(); } }

输出结果:
GetIEnumerator
MoveNext true
Current
1
MoveNext true
Current
2
MoveNext true
Current
3
MoveNext true
Current
4
MoveNext true
Current
5
MoveNext false

通过输出结果,我们可以发现,foreach在运行时会先调用ConstArrayList的GetIEnumerator函数获取一个ConstArrayListEnumeratorSimple,之后通过循环调用ConstArrayListEnumeratorSimple的MoveNext函数,index后移,更新Current属性,然后返回Current属性,直到MoveNext返回false。

总结一下:
GetIEnumerator()负责获取枚举器。
MoveNext()负责让Current获取下一个值,并判断遍历是否结束。
Current负责返回当前指向的值。
Rest()负责重置枚举器的状态(在foreach中没有用到)
这些就是IEnumerable,IEnumerator的基本工作原理了。

其次我们发现:

ConstArrayList constArrayList = new ConstArrayList();
foreach(int item in constArrayList) { writeLine(item); }

其实就等价于:

ConstArrayList constArrayList = new ConstArrayList();
IEnumerator enumeratorSimple = constArrayList.GetEnumerator();
while (enumeratorSimple.MoveNext())
{
    int item = (int)enumeratorSimple.Current; WriteLine(item); }

也就是说foreach其实是一种语法糖,用来简化对可枚举元素的遍历代码。而被遍历的类通过实现IEnumerable接口和一个相关的IEnumerator枚举器来实现遍历功能。

猜你喜欢

转载自www.cnblogs.com/gaoxianzhi/p/11949133.html