foreach ステートメントで Visual C# クラスを使用できるようにします
この記事では、 インターフェイスと インターフェイスを使用 IEnumerable
して、 IEnumerator
ステートメントで使用できるクラスを作成する方法について foreach
説明します。
元の製品バージョン: Visual Studio
元の KB 番号: 322022
IEnumerator インターフェイス
IEnumerable
と IEnumerator
は一緒に頻繁に使用されます。 これらのインターフェイスは似ていますが (名前も似ていますが)、目的は異なります。
インターフェイスは IEnumerator
、クラスの内部にあるコレクションに対して反復機能を提供します。 IEnumerator
では、次の 3 つのメソッドを実装する必要があります。
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
しない場合は、 メソッドIEnumerable
から インターフェイスに戻り値をGetEnumerator
IEnumerator
キャストすることはできません。
要約すると、 を IEnumerable
使用するには、 クラスが を実装 IEnumerator
する必要があります。 のサポートを提供する場合は、両方のインターフェイスを foreach
実装します。
ステップ バイ ステップの例
次の例では、これらのインターフェイスを使用する方法を示します。 この例では、 IEnumerator
インターフェイスと IEnumerable
インターフェイスを という名前 cars
のクラスで使用します。 クラスには cars
、オブジェクトの car
内部配列があります。 クライアント アプリケーションは、これら 2 つのインターフェイスの実装のために、 コンストラクトを 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」と入力します。
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」と入力します。
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);
}
}
}
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示