【C#】 26. 关于IEnumerable和IEnumerator

来源:互联网 发布:不用账号登录知乎 编辑:程序博客网 时间:2024/05/16 19:40

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

今天就写一点关于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();        }    }



0 0