【C#】イテレーターとは(基本、使い方)

イテレーターは、コレクションまたはシーケンスの要素を一つずつ返す方法を提供します。これにより、コレクションの全体をメモリに保持することなく、要求されたときに各要素を生成して返すことができます。

イテレーター

イテレーターを使用する主な利点は、効率的なリソース利用と、コレクションの処理をより柔軟に行えることです。yield return ステートメントを使うと、メソッドの実行を一時停止し、現在の呼び出しコンテキストを保持した状態で値を呼び出し元に返すことができます。その後、次の要素が要求されると、メソッドは停止した場所から実行を再開します。

イテレーターは、foreach ループなど、コレクションを一つずつ走査するシナリオで特に有用です。イテレーターメソッドやプロパティは、IEnumerable インターフェースや IEnumerable<T> インターフェースを実装することで、任意のコレクション型に対して動作します。これにより、カスタムの反復処理を簡単に実装でき、コードの再利用性と可読性が向上します。

サンプル

yield returnを使った一般的な用途は、条件に基づいてフィルターされた要素のシーケンスを生成することです。以下の例では、特定の条件(この場合は偶数のみを対象とする)に一致する数値のみを返すメソッドを作成します。

偶数のみを返すシンプルな例

// 1から10までの偶数を出力します
foreach (var number in EvenNumbers(10))
{
    Console.WriteLine(number);
}

// 指定された上限までの偶数を生成するメソッド
IEnumerable<int> EvenNumbers(int limit)
{
    for (int i = 1; i <= limit; i++)
    {
        if (i % 2 == 0)
        {
            yield return i;
        }
    }
}

この例では、EvenNumbersメソッドは1からlimitまでの整数をループし、各数値が偶数かどうかを確認します。偶数の場合、その数値はyield returnによって返されます。これにより、メソッドの呼び出し元は偶数のみを含むシーケンスを受け取ります。

yield returnを使用することで、メソッドの呼び出し元はメソッドが完全に終了するのを待つことなく、結果を逐次的に受け取ることができます。これは、リソースを節約し、アプリケーションのパフォーマンスを向上させるのに役立ちます。また、大量のデータを扱う際にメモリ使用量を削減する効果もあります。

 実行結果

2
4
6
8
10

IEnumerableについて

IEnumerableIEnumerable<T>は、C#のSystem.Collections名前空間にあるインターフェースで、コレクションや配列などのシーケンスを反復処理するための標準的な方法を提供します。これらのインターフェースを実装することで、コレクション内の各要素を一つずつ順番にアクセスできるようになります。主にforeachループでの使用を目的としています。

IEnumerableインターフェース

  • IEnumerableは、非ジェネリックなコレクションに対して使用されます。
  • このインターフェースには、GetEnumeratorメソッドが定義されています。このメソッドは、IEnumeratorインターフェースを実装するオブジェクトを返します。
  • IEnumeratorオブジェクトを使用して、コレクションを反復処理し、コレクション内の現在の要素を取得し、次の要素に移動します。

IEnumerable<T>インターフェース

  • IEnumerable<T>は、ジェネリックなコレクションに対して使用されるインターフェースで、IEnumerableのジェネリック版です。
  • ジェネリックなIEnumerable<T>インターフェースも、GetEnumeratorメソッドを定義していますが、このメソッドはIEnumerator<T>インターフェースを実装するオブジェクトを返します。
  • IEnumerator<T>はジェネリックなIEnumeratorインターフェースであり、型安全な方法でコレクションを反復処理することができます。

使用例

IEnumerableまたはIEnumerable<T>を実装するクラスは、以下のようにforeachループで簡単に反復処理することができます。

IEnumerable<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
foreach (int number in numbers)
{
    Console.WriteLine(number);
}

この例では、List<int>IEnumerable<int>を実装しているため、foreachループを使ってリストの各要素を順に処理できます。

まとめ

IEnumerableIEnumerable<T>インターフェースは、コレクションを扱う際の非常に重要な部分です。これらを理解し、適切に利用することで、C#におけるコレクションの反復処理がより効率的で柔軟になります。また、これらのインターフェースを利用することで、カスタムコレクションでもforeachループを使用できるようになり、コードの可読性と保守性が向上します。

IEnumeratorについて

IEnumeratorIEnumerator<T>は、C#のSystem.CollectionsおよびSystem.Collections.Generic名前空間にあるインターフェースで、コレクション内の要素を順番に列挙するための機構を提供します。これらはIEnumerableIEnumerable<T>インターフェースと密接に関連しており、コレクションを一つずつ反復処理する際に使用されます。

IEnumeratorインターフェース

  • IEnumeratorは、非ジェネリックなコレクションを反復処理するためのインターフェースです。
  • 主なメンバーは以下の通りです。
    • MoveNext(): コレクションの次の要素に移動します。次の要素が存在する場合はtrueを返し、そうでない場合はfalseを返します。このメソッドは初めて呼び出されたときにコレクションの最初の要素の前に位置しています。
    • Current: コレクション内の現在の要素を取得します。このプロパティはobject型の値を返します。
    • Reset(): 列挙子を初期位置、つまりコレクションの最初の要素の前にリセットします。

IEnumerator<T>インターフェース

  • IEnumerator<T>は、IEnumeratorのジェネリック版で、型安全な方法でコレクションを反復処理するために使用されます。
  • IEnumeratorと同様のメンバーを持ちますが、CurrentプロパティはT型の値を返します。これにより、キャストの必要性がなくなり、型安全性が確保されます。

使用例

IEnumerableIEnumerable<T>インターフェースを実装するコレクションクラスは、内部的にIEnumeratorまたはIEnumerator<T>インターフェースを実装するオブジェクトをGetEnumeratorメソッドを通じて提供します。foreachループはこのメカニズムを利用してコレクションを反復処理しますが、直接IEnumeratorを使用することも可能です。

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
IEnumerator<int> enumerator = numbers.GetEnumerator();

while (enumerator.MoveNext())
{
    int number = enumerator.Current;
    Console.WriteLine(number);
}

この例では、List<T>GetEnumeratorメソッドを呼び出してIEnumerator<int>を取得し、MoveNextメソッドとCurrentプロパティを使用してリストの各要素を反復処理しています。

まとめ

IEnumeratorIEnumerator<T>インターフェースは、コレクション内の要素を順にアクセスするための基本的なインターフェースです。これらは主にforeachループの背後で動作し、コレクションの反復処理を容易にします。また、これらのインターフェースを直接使用することで、コレクションのカスタム反復処理を実装することも可能です。

C#

Posted by hidepon