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

IEnumerable<T>, IEnumerator<T>インターフェイスを実装した独自のクラスを作成し、foreachに対応します。

概要

こちらの記事ではIEnumeratorインターフェイスを実装しforeachに対応したクラスを作成するコードを紹介しました。 この記事では、ジェネリクスに対応した、IEnumerable<T>, IEnumerator<T> インターフェイスを実装するコードを紹介します。

プログラム例

Windows Formアプリケーションを作成します。

UI

下図のUIを作成します。ButtonとTextBoxを配置します。

コード

MyClass.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CustomIEnumeratorT
{
  public class MyClass : IEnumerable<string>
  {
    IEnumerator IEnumerable.GetEnumerator()
    {
      return new MyClassProc(); 
    }
    
    IEnumerator<string> IEnumerable<string>.GetEnumerator()
    {
      return new MyClassProc(); 
    }
  }
}
MyClassProc.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CustomIEnumeratorT
{
  public class MyClassProc : IEnumerator<string>
  {
    int index = 0;
    public void Dispose()
    {
    }

    public bool MoveNext()
    {
      index++;

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

    public void Reset()
    {
      index = 0;
    }

    public string Current
    {
      get
      {
        switch (index)
        {
          case 1:
            return "ぺんぎんクッキー";
          case 2:
            return "らくだキャラメル";
          case 3:
            return "しろくまアイス";
          case 4:
            return "かるがもサブレ";
          case 5:
            return "きつねカステラ";
          default:
            return "none";
        }
      }
    }
    
    object IEnumerator.Current
    {
      get
      {
        switch (index)
        {
          case 1:
            return "ぺんぎんクッキー";
          case 2:
            return "らくだキャラメル";
          case 3:
            return "しろくまアイス";
          case 4:
            return "かるがもサブレ";
          case 5:
            return "きつねカステラ";
          default:
            return "none"; 
        }
      }
    }
    
  }
}
フォームのコード
namespace CustomIEnumeratorT
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

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

      foreach (string s in m)
      {
        textBox1.Text += s + "\r\n";
      }
    }
  }
}

解説

MyClassIEnumerable<T> インターフェイスを継承します。MyClassには次のメソッドを実装します。
  • IEnumerator IEnumerable.GetEnumerator()
  • IEnumerator<string> IEnumerable<string>.GetEnumerator()

2つのメソッドは明示的なインターフェイスメンバーの実装でも動作します。 (明示的なインターフェイスメンバーの実装の詳細はこちらの記事を参照してください。)
下記コードのように、IEnumerator<string>を返すGetEnumerator() メソッドをpublicにして実装しても動作します。
MyClass.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CustomIEnumeratorT
{
  public class MyClass : IEnumerable<string>
  {
    IEnumerator IEnumerable.GetEnumerator()
    {
      return new MyClassProc(); 
    }
    
    public IEnumerator<string> GetEnumerator()
    {
      return new MyClassProc();
    }
  }
}

MyClassProc クラスでは、IEnumerator<T> インターフェイスを実装します。
MyClassProcには次のメソッドを実装します。
  • public void Dispose()
  • public bool MoveNext()
  • public void Reset()
  • public <T> Current
  • object IEnumerator.Current

なお、下記コードのように、明示的なインターフェイスメンバーの実装で記述しても動作します。
  public class MyClassProc : IEnumerator<string>
  {
    int index = 0;
    void IDisposable.Dispose()
    {
    }

    bool IEnumerator.MoveNext()
    {
      /* 中略 */
    }

    void IEnumerator.Reset()
    {
      /* 中略 */
    }

    string IEnumerator<string>.Current
    {
      /* 中略 */
    }
    
    object IEnumerator.Current
    {
      /* 中略 */
    }
  }

フォームではMyClassのインスタンスを作成し、foreachループを実行します。ループ要素の値をテキストボックスに表示します。
    private void button1_Click(object sender, EventArgs e)
    {
      MyClass m = new MyClass();

      foreach (string s in m)
      {
        textBox1.Text += s + "\r\n";
      }
    }

実行結果

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


[button1]をクリックします。foreach文でループし、MyClass の IEnumerator<string> を取得し、 IEnumeratorの要素をひとつづつ取得してテキストボックスに値を表示している動作が確認できます。


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