我眼中的IEnumerable与IEnumerator

  最近在做项目中看到IEnumerable和IEnumberator,原来做MVC接触过,只知道是一个Collection要支持foreach方式的遍历,必须实现IEnumerable接口(亦即,必须以某种方式返回IEnumerator object)。这次就这个问题好好总结下,方便以后查找。

  在网上查了一些资料,自己总结下。

  public interface IEnumerable
{
    

// 摘要:
// 返回一个循环访问集合的枚举数。
//
// 返回结果:
// 一个可用于循环访问集合的 System.Collections.IEnumerator 对象。
[DispId(-4)]

IEnumerator GetEnumerator();
}
 
public interface IEnumerator
{
   

// 摘要:
// 获取集合中的当前元素。
//
// 返回结果:
// 集合中的当前元素。
object Current { get; }

// 摘要:
// 将枚举数推进到集合的下一个元素。
//
// 返回结果:
// 如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false。
//
// 异常:
// System.InvalidOperationException:
// 在创建了枚举数后集合被修改了。
bool MoveNext();
//
// 摘要:
// 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
//
// 异常:
// System.InvalidOperationException:
// 在创建了枚举数后集合被修改了。
void Reset();


}

在对象浏览器上找到IEnumerable、IEnumerator,可知:

  1、IEnumerable是一个声明式的interface,继承该接口的class都是可枚举的(enumerable),但是并没有具体说明如何实现枚举器(iterator)。

  2、IEnumerator是一个实现式的interface,ienumerator obj其实就是一个iterator。

  3、IEnumerator和IEnumerable通过IEnumerable.GetIEnumerator()建立连系,client可以通过IEnumerable的GetEnumerator()得到IEnumerator object。

 

华丽的分界线--------------------------------------------------------

  一个类A继承了IEnumerator,也就是实现Current属性,MoveNext方法,Reset方法。只要实现这些方法,这个类A就可以用foreach这种语法了。

   IEnumerable接口主要实现了GetEnumerator方法,该方法返回一个IEnumerator。一个类B实现IEnumerable接口后,调用foreach语法的时候,会自动的调用GetEnumerator方法,然后在这个IEnumerator中遍历。

所以只要实现两者之中任意一个接口,就可以用foreach语法了。但是本质上都是对IEnumerator做foreach,只是一个是直接,一个是间接。

代码说明:

比如类A实现了IEumerator

foreach(Foo item in A)

{

  //write code here

}

上面代码等同于下面的代码:

IEnumerator bat=A.GetIEnumerator;

while (bat.MoveNext()) 

   item = (Foo)bat.Current() 
   ... 

如果一个类,同时实现了IEnumerator<T>,IEnumerable<T>,那么就是糟糕的设计

因为用foreach语法的时候,会先调用IEnumerable的GetEnumerator方法。这是经过测试的。

你可能感兴趣的:(enum)