使用foreach可以方便地遍历集合,但是这些集合都是系统内置的,如何构造自定义的集合也可以用foreach来遍历呢?
这里涉及两个接口,IEnumerable和IEnumerator。通过实现这两个接口,就可以了。
下面给出一个简单的Demo
  1using System;
  2using System.Collections.Generic;
  3using System.Linq;
  4using System.Text;
  5using System.Collections;
  6
  7namespace CustomCollection
  8{
  9    public class Person
 10    {
 11        public string fname;
 12        public string lname;
 13        public Person(string first, string second)
 14        {
 15            this.fname = first;
 16            this.lname = second;
 17        }

 18        public override string ToString()
 19        {
 20            return this.fname + " " + this.lname;
 21        }

 22    }

 23    public class People : IEnumerable
 24    {
 25
 26        IEnumerable Members
 34
 35        private Person[] _people;
 36
 37        public People(Person[] people)
 38        {
 39            _people = new Person[people.Length];
 40            for (int i = 0; i < people.Length; i++)
 41            {
 42                _people[i] = people[i];
 43            }

 44        }

 45    }

 46    public class PeopleEnum : IEnumerator
 47    {
 48        public Person[] list;
 49        private int position = -1;
 50        public PeopleEnum(Person[] people)
 51        {
 52            list = people;
 53        }

 54
 55        IEnumerator Members
 84    }

 85    public class CustomCollection
 86    {
 87        static void Main(string[] args)
 88        {
 89            Person[] peopleArray = new Person[3]
 90            {
 91                new Person("John""Smith"),
 92                new Person("Jim""Johnson"),
 93                new Person("Sue""Rabon"),
 94            }
;
 95
 96            People peopleList = new People(peopleArray);
 97            foreach (Person p in peopleList)
 98                Console.WriteLine(p);
 99        }

100    }

101}

通过调试发现,Reset似乎没有被调用,到博客园搜了一下,验证了自己的判断,看到了一个文章
http://www.cnblogs.com/Daview/archive/2006/09/15/505317.html

不看不知道,以前有被问到如何实现自定义的集合支持foreach遍历,当时脱口而出实现那个两个接口。现在看来,这真的是初学者的无知,不是简单定义一个类型实现IEnumerable和IEnumerator就可以了。受Reset没被调用的影响,应该定义两个类型分别实现接口,否则就会出现集合遍历第二遍的失败。

posted @ 2008-06-27 16:23 sunlei 阅读(125) 评论(0) 编辑
在.net环境里,如果需要遍历集合的话,常用的就是foreach,根据Effective C#所说,也是最佳的实践方式。
下面首先比较各种遍历集合的方式:
 1int [] foo = new int[100];
 2
 3// Loop 1:
 4foreach ( int i in foo)
 5  Console.WriteLine( i.ToString( ));
 6
 7// Loop 2:
 8for ( int index = 0;
 9  index < foo.Length;
10  index++ )
11  Console.WriteLine( foo[index].ToString( ));
12
13// Loop 3:
14int len = foo.Length;
15for ( int index = 0;
16  index < len;
17  index++ )
18  Console.WriteLine( foo[index].ToString( ));
第一种是foreach,第二种是传统的for,第三种看似对第二种做了“优化”。
有过C++经验的人都会觉得第三种的优化很正常,但是C#的编译器可不这么想。由于C#强调安全编程,对象的访问都会检查是否越界。不管我们是不是自己保证不越界,编译器都会帮我们进行越界检查。因此,第三种实际上会产生两次下标检查。
 1// Loop 3, as generated by compiler:
 2int len = foo.Length;
 3for ( int index = 0;
 4  index < len;
 5  index++ )
 6{
 7  if ( index < foo.Length )
 8    Console.WriteLine( foo[index].ToString( ));
 9  else
10    throw new IndexOutOfRangeException( );
11}
是的,编译器确实做了两次下标检查,呵呵,帮倒忙了。
posted @ 2008-06-27 16:03 sunlei 阅读(400) 评论(0) 编辑