IEnumerator和IEnumerable是 .NET内置的接口,用来为集合类添加遍历的功能。然而两者高在一起,让我刚开始学习时头痛不已。查看MSDN和网上资料后,将自己的收获整理下来:
看着两者的英文名,我们大概可以猜一下:
IEnumerable的实现标志该类具有了枚举的能力,并且在适当的时机可以返回迭代器。它只有一个GetEnumerator()
IEnumerator GetEnumerator();
IEnumerator的实现标志着该类具有迭代器的功能,并且允许继承该接口的类制定自己的迭代规则,它有:
object Current{get;} //返回当前位置的元素
bool MoveNext() //移动到下一个元素;
void Reset() //重置迭代位置到开始处
为了迭代,我们必须需要一个标识当前迭代位置的字段,所以请再为迭代器添加一个index的字段吧。
index初始值为-1,MoveNext() 就是调整index的值,将迭代的位置向后移动,当超出界限时返回False,表示迭代结束,否则为True;
-----------------------------------------------分割线---------------------------------------------------------
下面通过一个例子理解一下:
Person类
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
People类 (继承自IEnumerable 包含一个People类型的数组)
class People : IEnumerable
{
private Person[] pers;
public People(Person[] pers)
{
this.pers = pers;
}
public IEnumerator GetEnumerator()
{
return new PeopleEnum(pers);
}
}
PeopleEnum类(继承IEnumerator用于产生迭代)
class PeopleEnum : IEnumerator
{
private int index = -1;
private Person[] pers;
public PeopleEnum(Person [] pers)
{
this.pers=pers;
}
public object Current
{
get
{
try
{
return pers[index];
}
catch(Exception e)
{
throw e;
}
}
}
public bool MoveNext()
{
return ++index < pers.Length;
}
public void Reset()
{
index = -1;
}
}
主函数测试
public class Test
{
static void Main()
{
Person[] pers = { new Person { FirstName = "A", LastName = "a" }, new Person { FirstName = "B", LastName = "b" } };
People peo = new People(pers);
IEnumerator enrator = peo.GetEnumerator();
while (enrator.MoveNext())
{
Console.WriteLine( ((Person)enrator.Current ).FirstName +"::"+((Person)enrator.Current).LastName);
}
}
}
请注意,PeopleEnum继承自IEnumerator,所以可以类型转换为IEnumberator。
在主函数中,先生成一个Person数组,然后用这个数组初始化一个People的对象,因为People实现了IEnmerable所以它能够迭代枚举,并可以返回一个枚举器IEnumerator,而不巧的是,IEnumerable接口并没有包含怎么实现迭代,所以还需要继承自IEnumberator的PeopleEnum类来产生一个迭代器。
这样一切就都具备了,开始While循环迭代People集合。
运行结果: