IEnumerable, IEnumeratorインターフェイスを実装しforeachに対応したクラスを作成する - C#

ここではIEnumeratorインターフェイスを実装し foreachに対応した自作クラスを作成するコードを紹介します。
補足
genericsを使ったIEnumerator<T>インターフェイスの実装方法はこちらの記事を参照してください

概要

IEnumerable インターフェイスを実装すると foreach文に対応できます。
IEnumerable インターフェイスをクラスに実装する場合は、IEnumerator.GetEnumerator() メソッドをクラスに実装する必要があります。
GetEnumerator() メソッドは IEnumerator オブジェクトを返します。 IEnumerator オブジェクトインターフェイスを実装した MyClassProcクラスでは、MoveNext Reset Current IEnumerator.Current を実装します。

プログラム例:  

UI

コード

フォームのコードは下記です。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CustomIEnumerator
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      MyClass m = new MyClass();

      foreach (int i in m) {
        textBox1.Text += Convert.ToString(i)+"\r\n";
      }

    }
  }
}

フォームから参照される MyClass クラスの実装です。
MyClass.cs
using System.Collections;

namespace CustomIEnumerator
{
  class MyClass : IEnumerable
  {
    IEnumerator IEnumerable.GetEnumerator()
    {
      return new MyClassProc();
    }
  }
}


IEnumeratorインターフェイスを実装した MyClassProc クラスのコードです。
MyClassProc.cs
using System.Collections;

namespace CustomIEnumerator
{
  class MyClassProc : IEnumerator
  {
    int index;

    public bool MoveNext()
    {
      index++;

      if (10 < index)
      {
        return false;
      }
      else
      {
        return true;
      }
    }

    public void Reset()
    {
      index = 0;
    }

    object IEnumerator.Current
    {
      get
      {
        return index;
      }
    }
  }
}

解説

IEnumerableインターフェイスの定義(規約)は下記コードです。
IEnumerableインターフェイスを実装したクラスでは、GetEnumerator() メソッドの実装が必要です。
IEnumerableの定義(抜粋)
 public interface IEnumerable
    {
        [Pure]
        [DispId(-4)]
        IEnumerator GetEnumerator();
    }
IEnumerableインターフェイスを実装した、MyClass では、GetEnumerator() メソッドを実装します。
GetEnumerator() メソッドは、IEnumerator インターフェイスをを実装したオブジェクトを返します。 今回の例では、IEnumerator インターフェイスを実装した MyClassProc クラスを返します。
  class MyClass : IEnumerable
  {
    IEnumerator IEnumerable.GetEnumerator()
    {
      return new MyClassProc();
    }
  }

なお、次のコードでも問題ないです。
  class MyClass : IEnumerable
  {
    public IEnumerator GetEnumerator()
    {
      return new MyClassProc();
    }
  }
MyClassProcクラスでは、MoveNext Reset Current IEnumerator.Current を実装します。
MoveNextメソッドでは、indexカウンタを増加します。カウンタの値が10以下であれば、false を返し、次の要素があることを示します。 10以上の場合は、true を返し要素がないことを示します。
MyClass を foreach文でループした場合、10までループして終了する動作になります。
    public bool MoveNext()
    {
      index++;

      if (10 < index)
      {
        return false;
      }
      else
      {
        return true;
      }
    }

Resetメソッドではカウンタの値を0に戻します。
    public void Reset()
    {
      index = 0;
    }

Currentプロパティでは現在のインデックスの値を返します。
    public int Current
    {
      get
      {
        return index;
      }
    }

    object IEnumerator.Current
    {
      get
      {
        return index;
      }
    }

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。テキストボックスに結果が表示されます。


著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2023-12-27
作成日: 2011-02-05
iPentec all rights reserverd.