C#中IEnumerable与IEnumerator接口定义了对集合的简单迭代。IEnumerable是一个声明式的接口,声明实现该接口的类是“可迭代(enumerable)”的,但并没有说明如何实现“迭代器(iterator)”。IEnumerator是一个实现式的接口,实现IEnumerator接口的类就是一个迭代器。
IEnumerable和IEnumerator通过IEnumerable的GetEnumerator()方法建立了连接,可以通过该方法得到一个迭代器对象。在这个意义上,可以将GetEnumerator()看作IEnumerator的工厂方法也未尝不可。一般,我们将迭代器作为内部类实现,这样可以尽量少的向外暴露无关的类。MSDN示例
一个Collection要支持foreach方式的遍历,必须实现IEnumerable接口(亦即,必须以某种方式返回迭代器对象:IEnumerator)。迭代器可用于读取集合中的数据,但不能用于修改基础集合。
using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class Program : IEnumerable
{
private class ListBoxEnumerator : IEnumerator
{
public ListBoxEnumerator(Program lbt)
{
this.lbt = lbt;
this.index = -1;
}
public bool MoveNext()
{
index++;
if (index >= lbt.strings.Length)
return false;
else
return true;
}
public void Reset()
{
index = -1;
}
public object Current
{
get
{
return (lbt[index]);
}
}
private Program lbt;
private int index;
}
public IEnumerator GetEnumerator()
{
return (IEnumerator)new ListBoxEnumerator(this);
}
public Program(params string[] initialStrings)
{
strings = new String[8];
foreach (string s in initialStrings)
{
strings[ctr++] = s;
}
}
public void Add(string theString)
{
strings[ctr] = theString;
ctr++;
}
public string this[int index]
{
get
{
if (index < 0 || index >= strings.Length)
{
Console.WriteLine("index is wrong");
return("wrong");
}
return strings[index];
}
set
{
strings[index] = value;
}
}
public int GetNumEntries()
{
return ctr;
}
private string[] strings;
private int ctr = 0;
public class Tester
{
static void Main(string[] args)
{
Program lbt = new Program("hello", "world");
lbt.Add("who");
lbt.Add("is");
lbt.Add("John");
lbt.Add("Galt");
string subst = "universe";
lbt[1] = subst;
foreach (string s in lbt)
{
Console.WriteLine("Value:{0}", s);
}
}
}
}
}
当程序 执行到 foreach (string s in lbt)
{
Console.WriteLine("Value:{0}", s);
}
之时,然后是调用public IEnumerator GetEnumerator(),
再然后 public ListBoxEnumerator(Program lbt)
public bool MoveNext()
public object Current
循环往复,这就是说明要想实现foreach,就必须实现IEnumerator接口
注:
平常使用foreach in 的时候都是用的系统定义好的集合类(实现ICollection接口)。比如 arrayList,stringDictionary ,数组等。这些是平台封装好的,已近实现了IEnumerator 接口了。 要让自己写的类也能时候foreach 就必须 在编写类的时候实现该接口。 这样就可以事后foreach遍历了。 比如 定义一个 people 的类,实现了IEnumerator接口。 有一个数组 People[] tempPeople , 那么 就可以用: foreach( p in tempPeople) { console.writeline(p.name); }