IEnumerable与IEnumerator
转自:http://www.cnblogs.com/ArtofDesign/p/3612492.html
C#中,我们通常可以用foreach语句来遍历数组或集合,下面深入探讨一下其工作原理
①自定义集合MyList
为了说明使用IEnumerable和IEnumerator接口,从而让数组或集合支持foreach语句的原理,我们首先自定义一个简单的链表形集合MyList,其中仅实现了AddData方法,其他相关方法没有写出,代码如下:
//集合包含的项,即所谓的节点
public class DataItem
{
public DataItem Next { get; set; }
public object Data { get; set; }
public DataItem(object data)
{
this.Data = data;
}
}
//自定义集合类
public class MyList
{
public DataItem FirstItem { get; set; }
public DataItem LastItem { get; set; }
public void AddData(object data)
{
DataItem newItem = new DataItem(data);
if (this.FirstItem == null)
{
this.FirstItem = newItem;
this.LastItem = newItem;
}
else
{
this.LastItem.Next = newItem;
this.LastItem = newItem;
}
}
}
②IEnumerable接口
foreach在遍历集合的时候,实质上调用的是GetEnumerator方法,因此要使得集合支持foreach遍历,必须实现GetEnumerator方法,该方法定义在IEnumerable接口中,该接口定义如下:
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
③IEmunerator接口
因此只要让MyList继承IEnumerable接口,并实现GetEnumerator方法即可,可是该方法要求返回一个IEnumerator,现在我们还没任何地方实现这个IEmunerator接口,因此我们先来看看他的定义
public interface IEnumerator
{
//集合中的当前元素。
object Current { get; }
//如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false。
bool MoveNext();
//将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
void Reset();
}
④实现IEnumerator接口
从该接口的定义可以看出,foreach语句就是根据MoveNext方法和Current属性,一个一个遍历集合元素的,为了使得思路清晰,这里我们单独编写一个类来实现该接口,且该类会以上面的MyList为基础,以便MyList调用它
public class MyEnumerator:IEnumerator
{
private DataItem currentItem = new DataItem(null);
public MyEnumerator (MyList list) //使用MyList的实例来构造该类
{
this.currentItem.Next = list.FirstItem;
}
public object Current
{
get { return currentItem.Data; }
}
public bool MoveNext()
{
if(currentItem.Next != null)
{
currentItem = currentItem.Next;
return true;
}
else
{
return false;
}
}
public void Reset()
{
throw new NotImplementedException();
}
}
⑤实现IEnumerable接口
有了这个MyEnumerator后,就可以让MyList实现IEnumerable接口中的GetEnumerator方法了,向MyList中添加如下代码
public IEnumerator GetEnumerator()
{
return new MyEnumerator(this);
}
到此为止,虽然MyList的功能还十分不完善,但已经支持foreach语句遍历了,需要说明一点的是,不论MyList是否继承接口IEnumerable,只要实现了GetEnumerator方法,就可以支持foreach语句。
⑥yield return
上面整个过程对于演示foreach语句的原理相当有用,不过每次都这样去实现就太费劲了,C#中可以使用yield return语句来帮我们自动实现IEnumerator接口,一下使得工作轻松多了,对MyList中的GetEnumerator方法作如下修改即可抛弃繁琐的MyEnumerator了
public IEnumerator GetEnumerator()
{
//return new MyEnumerator(this);
DataItem curent = this.FirstItem;
while(curent != null)
{
yield return curent.Data;
curent = curent.Next;
}
}

浙公网安备 33010602011771号