浅谈枚举中的IEnumerator接口、foreach语句、yield语句以及搭配使用
时间:2010-11-10 来源:Mr_Lonely
1. IEnumerator接口:
foreach语句使用IEnumerator接口的方法和属性,迭代几何中的所有元素,这个接口中的属性和方法如下表所示:
MoveNext() |
移动到Collection的下一个元素上,如果有这个元素,该方法就返回true,否则返回false |
Current |
属性Current返回光标所在的元素 |
Reset() |
返回将光标重新定位于Collection的开头(许多枚举会抛出NotSupportedException) |
2. foreach语句:
C#的foreach语句不会解析为IL代码中的foreach语句.C#编译器会把foreach语句转换为IEnumerable接口的方法和属性.下面是一个简单的foreach语句,它迭代persons数组中的所有元素,并逐个显示它们:
foreach(Person p in persons)
{
Console.WriteLine(p);
}
foreach语句会解析为下面的代码段.首先,调用GetEnumerator()方法,获得数组的一个枚举.在while循环中—只要MoveNext()返回true—用Current属性访问数组中的元素.
IEnumerator enumerator =persons.GetEnumerator();
while(enumerator.MoveNext())
{
Person p=(Person)enumerator.Current;
Console.WriteLine(p);
}
3. yield语句:
C#1.0使用foreach语句可以轻松地迭代几何.在C#1.0中,创建枚举器仍需要做大量的工作.C#2.0添加了yield语句,以便于创建枚举器.
yield retrun语句返回集合的一个元素,并移动到下一个元素上.yield break可以停止迭代.
下面的例子是用yield return语句实现一个简单集合的代码.类CGYCollection包含GetEnumerator()方法.该方法的实现代码包含两个yield retur语句,它们分别返回字符串__ParaBara和Guangyue Cai
using System;
using System.Collections;
namespace Temp
{
class CGYCollection
{
public IEnumerator GetEnumerator()
{
yield return "__ParaBara";
yield return "Guangyue Cai";
}
}
}
包含yield语句的方法或者属性也称为迭代块,迭代块必须声明为返回IEnumerator或IEnumerable接口.这个块可以包含多个yield return语句或yield break语句,但不能包含return语句.现在做一个foreach语句的迭代其集合:
CGYCollection cgycollction = new CGYCollection();
foreach (string s in cgycollction)
{
Console.WriteLine(s);
}
结果为:
值得一提的是,类可以用默认方式通过GetEnumerator()方法迭代yield return返回的yield块.
下面是一个例子,GetEnumerator()方法返回一个包含names[]数组的各个成员名字,Reverse()方法逆序迭代成员名,Subset方法作一个搜索:
public class D9TecMembers
{
string[] names ={
"Wei Gao","Zhao Zhang","Changji Song","Zhike Chang","Denian Zhang", "Zhaotian Yang","Guangyue Cai"};
public IEnumerator GetEnumerator()
{
for (int i = 0; i < names.Length; i++)
{
yield return names[i];
}
}
public IEnumerable Reverse()
{
for (int i = names.Length-1; i >= 0; i--)
{
yield return names[i];
}
}
public IEnumerable Subset(int index, int length)
{
for (int i = index; i < index + length; i++)
{
yield return names[i];
}
}
}
Main方法:
static void Main(string[] args)
{
D9TecMembers titles = new D9TecMembers();
foreach (string title in titles)
{
Console.WriteLine(title);
}
Console.WriteLine();
foreach (string title in titles.Reverse())
{
Console.WriteLine(title);
}
Console.WriteLine();
foreach (string title in titles.Subset(1, 2))
{
Console.WriteLine(title);
}
}
得到以下结果: