IEnumerable和IEnumerator两个接口的语法定义。其实IEnumerable接口是非常的简单,只包含一个抽象的方法GetEnumerator(),它返回一个可用于循环访问集合的IEnumerator对象。IEnumerator对象有什么呢?它是一个真正的集合访问器,没有它,就不能使用foreach语句遍历集合或数组,因为只有IEnumerator对象才能访问集合中的项,假如连集合中的项都访问不了,那么进行集合的循环遍历是不可能的事情了。那么让我们看看IEnumerator接口有定义了什么东西。看下图我们知道IEnumerator接口定义了一个Current属性,MoveNext和Reset两个方法,这是多么的简约。既然IEnumerator对象时一个访问器,那至少应该有一个Current属性,来获取当前集合中的项吧。
- public class Garage
- {
- Car[] carArray = new Car[4]; //在Garage中定义一个Car类型的数组carArray,其实carArray在这里的本质是一个数组字段
- //启动时填充一些Car对象
- public Garage()
- {
- //为数组字段赋值
- carArray[0] = new Car("Rusty", 30);
- carArray[1] = new Car("Clunker", 50);
- carArray[2] = new Car("Zippy", 30);
- carArray[3] = new Car("Fred", 45);
- }
- }
- //这看起来好像是可行的
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("*********Fun with IEnumberable/IEnumerator************\n");
- Garage carLot = new Garage();
- //交出集合中的每一Car对象吗
- foreach (Car c in carLot)
- {
- Console.WriteLine("{0} is going {1} MPH", c.CarName, c.CurrentSpeed);
- }
- Console.ReadLine();
- }
- }
编译器通知我们Garage类没有实现名为GetEnumerator()的方法(显然用foreach遍历Garage对象是不可能的事情,因为Garage类没有实现GetEnumerator()方法,Garage对象就不可能返回一个IEnumerator对象,没有IEnumerator对象,就不可能调用方法MoveNext(),调用不了MoveNext,就不可能循环的了)。这个方法是有隐藏在System.collections命名空间中的IEnumerable接口定义的。(特别注意,其实我们循环遍历的都是对象而不是类,只是这个对象是一个集合对象)
要想Garage类也可以使用foreach遍历其中的项,那我们就要修改Garage类型使之支持这些接口,可以手工实现每一个方法,不过这得花费不少功夫。虽然自己开发GetEnumerator()、MoveNext()、Current和Reset()也没有问题,但有一个更简单的办法。因为System.Array类型和其他许多类型(如List)已经实现了IEnumerable和IEnumerator接口,你可以简单委托请求到System.Array,如下所示:
- namespace MyCarIEnumerator
- {
- public class Garage:IEnumerable
- {
- Car[] carArray = new Car[4];
- //启动时填充一些Car对象
- public Garage()
- {
- carArray[0] = new Car("Rusty", 30);
- carArray[1] = new Car("Clunker", 50);
- carArray[2] = new Car("Zippy", 30);
- carArray[3] = new Car("Fred", 45);
- }
- public IEnumerator GetEnumerator()
- {
- return this.carArray.GetEnumerator();
- }
- }
- }