本文演示如何使用 IEnumerable 接口和 IEnumerator 接口创建可在语句中使用的 foreach 类。
原始产品版本: Visual Studio
原始 KB 数: 322022
IEnumerator 接口
IEnumerable 并且 IEnumerator 经常一起使用。 尽管这些接口相似(并且具有类似的名称),但它们具有不同的用途。
该 IEnumerator 接口为类内部的集合提供迭代功能。 IEnumerator 要求实现三种方法:
该方法
MoveNext将集合索引递增 1,并返回一个布尔值,该值指示是否已到达集合的末尾。该方法
Reset将集合索引重置为 -1 的初始值。 这会使枚举器失效。该方法
Current返回当前对象的位置position。public bool MoveNext() { position++; return (position < carlist.Length); } public void Reset() { position = -1; } public object Current { get { return carlist[position];} }
IEnumerable 接口
该 IEnumerable 接口提供对 foreach 迭代的支持。 IEnumerable 要求实现 GetEnumerator 该方法。
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
何时使用哪个接口
最初,你可能会发现使用这些接口会令人困惑。 该 IEnumerator 接口提供对类中的集合类型对象的迭代。 该 IEnumerable 接口允许使用 foreach 循环进行枚举。 但是, GetEnumerator 接口的方法 IEnumerable 返回接口 IEnumerator 。 因此,若要实现 IEnumerable,还必须实现 IEnumerator。 如果未实现IEnumerator,则无法将返回值从GetEnumerator接口的方法IEnumerableIEnumerator强制转换为接口。
总之,使用 IEnumerable 类实现 IEnumerator的要求。 如果要为这两个接口提供支持 foreach,请实现这两个接口。
分步示例
以下示例演示如何使用这些接口。 在此示例中,在名为 <IEnumerator> 的类中使用和IEnumerable接口。 该 cars 类具有对象的内部数组 car 。 由于这两个 foreach 接口的实现,客户端应用程序可以使用构造来枚举此内部数组。
按照以下步骤在 Visual C# 中创建新的控制台应用程序项目:
- 开始Microsoft Visual Studio .NET 或 Visual Studio。
- 在 “文件” 菜单上,指向 “新建” ,然后单击 “项目” 。
- 单击“项目类型”下的“Visual C# 项目”,然后单击“模板”下的“控制台应用程序”。
- 在 “名称 ”框中,键入 ConsoleEnum。
将Class1.cs重命名为host.cs,然后将host.cs中的代码替换为以下代码:
using System; namespace ConsoleEnum { class host { [STAThread] static void Main(string[] args) { cars C = new cars(); Console.WriteLine("\nInternal Collection (Unsorted - IEnumerable,Enumerator)\n"); foreach(car c in C) Console.WriteLine(c.Make + "\t\t" + c.Year); Console.ReadLine(); } } }在“项目”菜单上,单击“添加类”,然后在“名称”框中键入汽车。
将car.cs中的代码替换为以下代码:
using System; using System.Collections; namespace ConsoleEnum { public class car { private int year; private string make; public car(string Make,int Year) { make=Make; year=Year; } public int Year { get {return year;} set {year=value;} } public string Make { get {return make;} set {make=value;} } }//end class }//end namespace在“项目”菜单上,单击“添加类”以向项目添加其他类,然后在“名称”框中键入汽车。
将cars.cs中的代码替换为以下代码:
using System; using System.Collections; namespace ConsoleEnum { public class cars : IEnumerator,IEnumerable { private car[] carlist; int position = -1; //Create internal array in constructor. public cars() { carlist= new car[6] { new car("Ford",1992), new car("Fiat",1988), new car("Buick",1932), new car("Ford",1932), new car("Dodge",1999), new car("Honda",1977) }; } //IEnumerator and IEnumerable require these methods. public IEnumerator GetEnumerator() { return (IEnumerator)this; } //IEnumerator public bool MoveNext() { position++; return (position < carlist.Length); } //IEnumerable public void Reset() { position = -1; } //IEnumerable public object Current { get { return carlist[position];} } } }运行该项目。
以下输出显示在 控制台 窗口中:
Ford 1992
Fiat 1988
Buick 1932
Ford 1932
Dodge 1999
Honda 1977
最佳做法
本文中的示例尽可能简单,以更好地解释这些接口的使用。 若要使代码更加可靠并确保代码使用当前的最佳做法准则,请按如下所示修改代码:
- 在嵌套类中实现
IEnumerator,以便可以创建多个枚举器。 - 为
Current此方法IEnumerator提供异常处理。 如果集合的内容发生更改,将reset调用该方法。 因此,当前枚举器失效,并且你会收到异常IndexOutOfRangeException。 其他情况也可能导致此异常。 因此,实现一个Try...Catch块来捕获此异常并引发InvalidOperationException异常。
using System;
using System.Collections;
namespace ConsoleEnum
{
public class cars : IEnumerable
{
private car[] carlist;
//Create internal array in constructor.
public cars()
{
carlist= new car[6]
{
new car("Ford",1992),
new car("Fiat",1988),
new car("Buick",1932),
new car("Ford",1932),
new car("Dodge",1999),
new car("Honda",1977)
};
}
//private enumerator class
private class MyEnumerator:IEnumerator
{
public car[] carlist;
int position = -1;
//constructor
public MyEnumerator(car[] list)
{
carlist=list;
}
private IEnumerator getEnumerator()
{
return (IEnumerator)this;
}
//IEnumerator
public bool MoveNext()
{
position++;
return (position < carlist.Length);
}
//IEnumerator
public void Reset()
{
position = -1;
}
//IEnumerator
public object Current
{
get
{
try
{
return carlist[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
} //end nested class
public IEnumerator GetEnumerator()
{
return new MyEnumerator(carlist);
}
}
}