C# でのコレクション操作入門 – IEnumerable と IEnumerator の基本的な使い方

この技術資料は、C# におけるコレクション操作の基本である IEnumerable と IEnumerator の使い方について、初学者向けにわかりやすく解説します。ジェネリックなコレクションの作成方法や、イテレータパターンの実装方法を学ぶことで、C# の基礎を理解し、より複雑なデータ構造に取り組む準備ができます。


1. はじめに

C# では、コレクション(複数の要素を扱うデータ構造)を操作する際に、IEnumerable<T> インターフェースと IEnumerator<T> インターフェースをよく使用します。これらを使うことで、コレクションの要素を順番に操作したり、繰り返し処理を行うことが簡単になります。この資料では、基本的な IEnumerable<T> と IEnumerator<T> の実装方法を例を交えて説明します。

2. コレクション操作の基本 – IEnumerable<T> と IEnumerator<T>

2.1 IEnumerable<T> とは?

IEnumerable<T> は、コレクションを反復処理できるインターフェースです。このインターフェースを実装することで、そのコレクションを foreach ループで繰り返し処理できるようになります。

2.2 IEnumerator<T> とは?

IEnumerator<T> は、コレクションの要素に順番にアクセスするためのインターフェースです。IEnumerable<T>は、この IEnumerator<T> を返す GetEnumerator メソッドを提供することで動作します。

3. SimpleArray<T> クラスの実装

ここでは、IEnumerable<T> と IEnumerator<T> を使用して、基本的なジェネリックコレクション SimpleArray<T> を実装してみます。

using System;
using System.Collections;
using System.Collections.Generic;

// SimpleArray クラスは、配列のジェネリックコレクションを表し、IEnumerable<T> インターフェースを実装しています。
public class SimpleArray<T> : IEnumerable<T>
{
    private T[] _array;

    // コンストラクタで配列を受け取り、_array にセットします。
    public SimpleArray(T[] array)
    {
        _array = array;
    }

    // ジェネリック型の IEnumerator<T> を返す GetEnumerator メソッド。
    public IEnumerator<T> GetEnumerator()
    {
        return new ArrayEnumerator(_array);
    }

    // 非ジェネリック型の IEnumerator を返すためのメソッド。上の GetEnumerator を呼び出しています。
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    // ArrayEnumerator クラスは、SimpleArray クラス内で使用するイテレータを定義します。
    private class ArrayEnumerator : IEnumerator<T>
    {
        private T[] _array;
        private int _position = -1; // 初期位置を -1 に設定

        // コンストラクタで配列を受け取り、_array にセットします。
        public ArrayEnumerator(T[] array)
        {
            _array = array;
        }

        // 現在の要素を取得します。
        public T Current
        {
            get
            {
                if (_position < 0 || _position >= _array.Length)
                    throw new InvalidOperationException("列挙子が無効な状態にあります。");
                return _array[_position];
            }
        }

        // IEnumerator.Current を実装。非ジェネリック版の Current を呼び出します。
        object IEnumerator.Current => Current;

        // 次の要素に進めるメソッド。成功したら true を返し、配列の終わりに達したら false を返します。
        public bool MoveNext()
        {
            _position++;
            return _position < _array.Length;
        }

        // イテレーションをリセットします。位置を -1 に戻します。
        public void Reset()
        {
            _position = -1;
        }

        // リソースを解放するためのメソッド。ここでは特に何もする必要はありません。
        public void Dispose()
        {
            // 必要なリソース解放処理があればここに記述しますが、この場合は特に何もしません。
        }
    }
}

3.1 実装のポイント

  • ジェネリックコレクションSimpleArray<T> クラスは、任意の型 T の配列を受け取り、それを内部で管理します。
  • GetEnumerator メソッド: このメソッドで IEnumerator<T> を返し、foreach ループを使ってコレクションの要素を繰り返し処理できるようにします。
  • ArrayEnumerator クラス: 内部クラスとして定義され、コレクションの各要素に順番にアクセスするためのロジックを提供します。

4. 使用例 – SimpleArray<T> クラスでのコレクション操作

以下のコードは、SimpleArray<int> を使用して配列の要素を繰り返し処理する例です。

class Program
{
    static void Main()
    {
        int[] numbers = { 1, 2, 3, 4, 5 };
        SimpleArray<int> simpleArray = new SimpleArray<int>(numbers);

        // SimpleArray<int> の各要素を順に出力します。
        foreach (int number in simpleArray)
        {
            Console.WriteLine(number);
        }
    }
}

4.1 実行結果

上記のコードを実行すると、配列の各要素が順番に出力されます。

1
2
3
4
5

5. まとめ

この資料では、C# の基本的なコレクション操作である IEnumerable<T> と IEnumerator<T> の使い方について解説しました。SimpleArray<T> クラスの実装を通じて、コレクションの要素を順番に処理する方法を理解できたでしょう。これらの基礎を理解することで、C# のより高度なデータ操作やカスタムコレクションの実装が可能になります。

6. 練習問題

  1. SimpleArray<T> クラスに、Count プロパティを追加して、コレクション内の要素数を取得できるようにしてみましょう。
  2. SimpleArray<T> クラスを継承して、新しいクラス ReversedSimpleArray<T> を作成し、配列の要素を逆順で列挙するようにしてみましょう。

C#

Posted by hidepon