代码改变世界

IEnumerable, IEnumerator接口

2017-06-04 17:06  Dirichlet  阅读(184)  评论(0编辑  收藏  举报

IEnumerable接口

//     Exposes the enumerator, which supports a simple iteration over a non-generic collection.
public interface IEnumerable {// Returns an enumerator that iterates through a collection. IEnumerator GetEnumerator(); }

IEnumerator接口

//     Supports a simple iteration over a nongeneric collection.
public interface IEnumerator {// Gets the current element in the collection. object Current { get; } // Advances the enumerator to the next element of the collection. bool MoveNext(); // Sets the enumerator to its initial position, which is before the first element in the collection. void Reset(); }

 

 示例1:

    class MyClass : IEnumerable
    {
        private int[] sources;

        public MyClass()
        {
            this.sources = new int[] { 0, 1, 3, 3, 4, 5, 5, 7, 8, 1, 3, 4, 9, 9, 9, 9, 90, 0, 0 };
        }

        public int this[int index]
        {
            get { return this.sources[index]; }
        }

        public int Length { get { return this.sources.Length; } }

        public IEnumerator GetEnumerator()
        {
            return new MyClassEnumerator(this);
        }
    }

    class MyClassEnumerator : IEnumerator
    {
        private MyClass myobject;
        private int index = -1;

        public MyClassEnumerator(MyClass myobject)
        {
            this.myobject = myobject;
        }

        public object Current
        {
            get { return this.myobject[index]; }
        }

        public bool MoveNext()
        {
            if (this.index < this.myobject.Length - 1)
            {
                this.index++;
                return true;
            }

            return false;
        }

        public void Reset() { this.index = -1; }
    }

        static void Main(string[] args)
        {
            MyClass myobject = new MyClass();

            foreach (var item in myobject)
            {
                Console.WriteLine(item);
            }

            return;
        }
View Code

 

示例2: 用yield关键字简化实现.

yield是一个语法糖, 编译器会重新翻译这段代码, 实际上是返回了一个实现了IEnumerator 的对象, 每一次的yield循环对应MoveNext, return this[i]对应于Current属性.

参考:http://www.cnblogs.com/artech/archive/2013/04/14/yield-in-wcf-02.html

    class MyClass : IEnumerable
    {
        private int[] sources;

        public MyClass()
        {
            this.sources = new int[] { 0, 1, 3, 3, 4, 5, 5, 7, 8, 1, 3, 4, 9, 9, 9, 9, 90, 0, 0 };
        }

        public int this[int index]
        {
            get { return this.sources[index]; }
        }

        public int Length { get { return this.sources.Length; } }

        public IEnumerator GetEnumerator()
        {
            //return new MyClassEnumerator(this);
            for (int i = 0; i < this.Length; i++)
            {
                yield return this[i];
            }
        }
    }

 

示例3: 一个对象同时实现了IEnumerable, IEnumerator. 这个实例仅供实验研究, 不推荐实际中应用.

提问: 为什么还要实现IEnumerable, 直接实现了IEnumerator就可以foreach不行吗?

回答: 请把枚举器想象成类似指针的功能, 可以遍历指向的集合.但是一个集合对象最好允许有多个枚举器, 如果集合对象直接实现IEnumerator, 集合对象和枚举器就耦合在一起,一个集合对象就只能有一个枚举器了,也就是它本身就是自己的枚举器。就算是不考虑支持多种枚举器,只考虑对一个枚举器的同时进行多次枚举,只实现IEnumerable也是做不到。

 1     class MyClass : IEnumerable, IEnumerator
 2     {
 3         private int[] sources;
 4         private int index = -1;
 5 
 6         public MyClass()
 7         {
 8             this.sources = new int[] { 0, 1, 3, 3, 4, 5, 5, 7, 8, 1, 3, 4, 9, 9, 9, 9, 90, 0, 0 };
 9         }
10 
11         public int this[int index]
12         {
13             get { return this.sources[index]; }
14         }
15 
16         public int Length { get { return this.sources.Length; } }
17 
18         public IEnumerator GetEnumerator()
19         {
20             //return new MyClassEnumerator(this);
21             for (int i = 0; i < this.Length; i++)
22             {
23                 yield return this[i];
24             }
25         }
26 
27         public object Current
28         {
29             get { return this[index]; }
30         }
31 
32         public bool MoveNext()
33         {
34             if (this.index < this.Length - 1)
35             {
36                 this.index++;
37                 return true;
38             }
39 
40             return false;
41         }
42 
43         public void Reset() { this.index = -1; }
44     }
45 
46         static void Main(string[] args)
47         {
48             MyClass myobject = new MyClass();
49 
50             foreach (var item in myobject)
51             {
52                 Console.WriteLine(item);
53             }
54 
55          }

 

参考:

http://www.cnblogs.com/artech/archive/2013/04/14/yield-in-wcf-02.html