【C#】 26. 关于IEnumerable跟IEnumerator

【C#】 26. 关于IEnumerable和IEnumerator

终于把硕士所有的课业都完成了。。。

今天就写一点关于IEnumerator和IEnumerable这两个概念,之前写金融模型的时候用到过,当时也没太搞清楚,这两天看了C#in Depth,觉得里面解释的不错,虽然例子有点错误。所以今天就写一篇关于这两个概念的文章。

首先,我有一个先入为主的概念,IEnumerable就好比是一个数组类型。一想到数组,我们就能很轻而易举地联想到Foreach遍历的语法。那么问题是Foreach是怎么实现的呢?答案就是你调用Foreach的时候这个类似数组的IEnumerable的数据类型会调用其内部的一个方法——GetEnumerator

,他返回一个IEnumerator类型。

具体的来说,这个IEnumerator类型里面包含了Current,MoveNext以及Reset方法。Foreach每次执行时就是在调用这三个方法。

下面是一个例子:本例中MyArray是一个实现了IEnumerable<int>的类型,其中有一个很重要的方法是GetEnumerator;返回一个实现IEnumerator<int>的Iterator,本身this(MyArray)作为参数。在main函数里面,for each的对象是MyArray类型数据,每次loop会先调用MoveNext,而后Current。Reset我觉得应该是For Each整个结束后,包括诸如Dispose等等的时候调用,但是我没有考证哈。最后我们就看到结果了。

 

最后值得一提的是GetEnumerator中可以使用yield return,这样就不需要Iterator这个类型了,非常直观方便,是C# 2.0及之后版本的语法。

    public class MyArray : IEnumerable<int>
    {
        public int[] values;
        public MyArray(int[] Array)
        {
            this.values = Array;
        }

        //实现接口IEnumerable
        public IEnumerator<int> GetEnumerator()
        {
            return new Iterator(this);
            //for (int i = 0; i < values.Length; i++)
            //{
            //    yield return values[i];
            //}
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

//IEnumerator实现类,MyArray作为成员
    public class Iterator : IEnumerator<int>
    { 
        private MyArray mMyArray;
        private int mPosition;

        public Iterator(MyArray myArray)
        {
            this.mMyArray = myArray;
            this.mPosition = -1;
        }
        //实现IEnumerator接口
        public int  Current
        {
	        get 
            { 
                //如果没有执行MoveNext就执行Current会报错
                //或者执行到最后一个元素之后
                if (mPosition == -1||mPosition == mMyArray.values.Length)
                {
                    throw new Exception();
                }
                else return mMyArray.values[mPosition];
            }
        }

        public bool  MoveNext()
        {
            bool isNotEnd;
            if (mPosition < mMyArray.values.Length-1)
            {
                mPosition++;
                isNotEnd = true;
            }
            else isNotEnd = false;
            return isNotEnd;
        }

        public void  Reset()
        {
            mPosition = -1;
        }

        public void Dispose()
        {}

        object System.Collections.IEnumerator.Current
        {
            get { throw new NotImplementedException(); }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyArray array = new MyArray(new int[] { 1, 2, 3, 4, 5 });
            foreach (var item in array)
            {
                Console.WriteLine(item.ToString());
            }
            Console.Read();
        }
    }


【C#】 26. 关于IEnumerable跟IEnumerator