IEnumerator和IEnumerable详解

Posted gaoxianzhi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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枚举器来实现遍历功能。

以上是关于IEnumerator和IEnumerable详解的主要内容,如果未能解决你的问题,请参考以下文章

转载 IEnumerable和IEnumerator 详解

IEnumerable和IEnumerator 详解

IEnumerable和IEnumerator详解

IEnumerator和IEnumerable详解

IEnumerable和IEnumerator 详解

IEnumerator和IEnumerable