本文示範如何使用 IEnumerable
和 IEnumerator
介面來建立可在 語句中使用的 foreach
類別。
原始產品版本: Visual Studio
原始 KB 編號: 322022
IEnumerator 介面
IEnumerable
和 IEnumerator
經常一起使用。 雖然這些介面很類似(且有類似的名稱),但它們有不同的用途。
介面 IEnumerator
提供類別內部集合的反覆功能。 IEnumerator
需要您實作三種方法:
方法
MoveNext
會將集合索引遞增 1,並傳回 bool,指出是否已到達集合結尾。方法,會將
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
的 方法IEnumerable
IEnumerator
轉換成 介面。
總而言之,使用 IEnumerable
會要求 類別實 IEnumerator
作 。 如果您想要提供 的支援 foreach
,請實作這兩個介面。
逐步說明範例
下列範例示範如何使用這些介面。 在此範例中, IEnumerator
和 IEnumerable
介面會用於名為 cars
的類別中。 類別 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
作 ,以便您可以建立多個列舉值。 - 為的方法
IEnumerator
提供例外狀況處理Current
。 如果集合的內容變更,則會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);
}
}
}