C#如何实现自定义集合的IEnumerable 和 IEnumerator 接口并使用foreach访问自定义集合

   抛砖引玉:                                                                                         

static void Main(string[] args)
{
    int[] array = new int[] { 5,4,3,2,1};
    foreach (int i in array)
        Console.WriteLine("Number:"+i);
    Console.ReadKey();            
}
/**
 * -------------执行结果-------------
 * Number:5
 * Number:4
 * Number:3
 * Number:2
 * Number:1
 * -------------执行结果-------------
 */

问题:为什么使用foreach可以遍历出数组中的所有元素呢?                  

原因:数组是可枚举类型,它可以按需提供枚举数,枚举数可以依次返回请求的数组的元素。而foreach结构被设计用来和可枚举类型一起使用,只要给foreach的遍历对象是可枚举类型,则她就会执行如下行为:

  1. 通过调用GetEnumerator方法获取对象(如:数组)的枚举数(即数组中的元素值)
  2. 从枚举数中请求每一项并把她作为迭代遍历

因为数组是可枚举类型,所以我就使用使用IEnumerator接口来实现枚举数以模仿foreach的循环遍历

实现代码如下:

static void Main(string[] args)
{
    int[] array = new int[] { 5,4,3,2,1};
    IEnumerator ie = array.GetEnumerator();//获取枚举数
    while (ie.MoveNext())//移动下一项
    {
        //最初,枚举数定位在集合中第一个元素前,在此位置上,Current 属性未定义
        //因此,在读取 Current 的值之前,必须调用 MoveNext 方法将枚举数提前到集合的第一个元素
        int i = (int)ie.Current;//获取当前项
        Console.WriteLine("Number:" + i);
    }      
}
   /**
    * -------------执行结果-------------
    * Number:5
    * Number:4
    * Number:3
    * Number:2
    * Number:1
    * -------------执行结果-------------
    */

实现IEnumerable 和 IEnumerator 接口                                                                    

以下示例演示如何实现自定义集合的IEnumerable 和 IEnumerator 接口,在此示例中,没有显式调用这些接口的成员,但实现了它们,以便支持使用 foreach循环访问该集合

要点:

  1. 显示实现IEnumerable接口的GetEnumerator成员函数
  2. 显示实现IEnumerator接口的Current,Reset(),MoveNext()

示意图:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{    
    // 实现IEnumerator接口
    public class PersonIEnumerator : IEnumerator
    {
        string[] Person;
        int position = -1;
        public PersonIEnumerator(string[] thePersons)
        {
            Person = new string[thePersons.Length];
            for (int i = 0; i < thePersons.Length; i++)
            {
                Person[i] = thePersons[i];
            }
        }
        //IEnumerator接口的特性1
        public object Current
        {
            get { return Person[position]; }
        }
        //IEnumerator接口的特性2
        public bool MoveNext()
        {
            if (position < Person.Length - 1)
            {
                position++;
                return true;
            }
            else
                return false;
        }
        //IEnumerator接口的特性3
        public void Reset()
        {
            position = -1;
        }
    }
    //实现IEnumerable接口
    public class MyPersons : IEnumerable
    {
        string[] strArr = new string[] { "周星驰", "莫言", "贝克汉姆", "林志颖" };
        //返回IEnumerator类型的对象
        public IEnumerator GetEnumerator()
        {
            return new PersonIEnumerator(strArr);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyPersons mp = new MyPersons();
            foreach (string name in mp)
            {
                Console.WriteLine("{0}", name);
            }
            Console.ReadKey();            
        }        
    }
    /**
     * -------------执行结果-------------
     * 周星驰
     * 莫言
     * 贝克汉姆
     * 林志颖
     * -------------执行结果-------------
     */
}

 

注:C# 语言的 foreach 语句隐藏了枚举数的复杂性。因此,建议使用 foreach,而不直接操作枚举数

原创文章,转载请注明出处:http://www.cnblogs.com/hongfei

posted @ 2013-01-23 16:20  曾是土木人  阅读(1566)  评论(1编辑  收藏  举报