列挙処理可能なクラスの実装

列挙クラス定義

namespace EnumeratorSample
{
    /// <summary>
    /// 数値範囲の列挙を行う2
    /// </summary>
    class RangeEnumerable2
    {
        private int from;
        private int count;
        private int step;

        /// <summary>
        /// 初期化
        /// </summary>
        /// <param name="from"></param>
        /// <param name="count"></param>
        /// <param name="step"></param>
        public RangeEnumerable2(int from, int count, int step)
        {
            this.from = from;
            this.count = count;
            this.step = step;
        }

        /// <summary>
        /// 列挙子を返す
        /// </summary>
        /// <returns></returns>
        public IEnumerable<int> GetEnumerable()
        {
            for (int i = from; i < from + count; i+=step)
            {
                yield return i;
            }
        }
    }

    /// <summary>
    /// 数値範囲の列挙を行う
    /// </summary>
    class RangeEnumerable : IEnumerable<int>
    {
        /*
         * IEnumerable<T>の実装バージョン。
         * このインターフェイスが非ジェネリックバージョンを継承しているので
         * すべて実装する場合はIEnumerator実装クラスが必要になってしまう。
         * 
         */

        private int from;
        private int count;

        /// <summary>
        /// 初期化
        /// </summary>
        /// <param name="from">開始値</param>
        /// <param name="count">カウントする数</param>
        public RangeEnumerable(int from, int count)
        {
            this.from = from;
            this.count = count;
        }

        #region IEnumerable<int> メンバ

        public IEnumerator<int> GetEnumerator()
        {
            for (int i = from; i < from + count; i++)
            {
                yield return i;
            }
        }

        #endregion

        #region IEnumerable メンバ

        /*
         * 異なるインターフェイス間で同名のメソッドが存在している場合の記述方法。詳細は下記参照。
         * ・どのインターフェイス実装かをフルネームで書く。
         * ・この場合はアクセス修飾子は書かない。(書くとビルドエラーになる)
         * 
         *明示的なインターフェイスの実装 (C# プログラミング ガイド)  
         * http://msdn.microsoft.com/ja-jp/library/ms173157.aspx
         */

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new EnumeratorSample.NonGenelic.RangeEnumrator(from, count);
        }

        #endregion
    }
}

namespace EnumeratorSample.NonGenelic
{
    /*
     * IEnumeratorインターフェイス実装は下記を参照
     * http://msdn.microsoft.com/ja-jp/library/system.collections.ienumerator.current%28VS.80%29.aspx
     * 
     */

    class RangeEnumrator : System.Collections.IEnumerator
    {
        private int[] array;
        private int idx;

        /// <summary>
        /// 初期化
        /// </summary>
        /// <param name="from"></param>
        /// <param name="count"></param>
        public RangeEnumrator(int from, int count)
        {
            array = new int[count];
            for (int i = 0; i < count; i++)
                array[i] = from + i;
            idx = -1;
        }

        #region IEnumerator メンバ

        public object Current
        {
            get
            {
                try
                {
                    return array[idx];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }

        public bool MoveNext()
        {
            idx++;
            return idx < array.Length;
        }

        public void Reset()
        {
            idx = -1;
        }

        #endregion
    }
}

上記列挙クラスの使用

/// <summary>
/// Window1.xaml の相互作用ロジック
/// </summary>
public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        //列挙処理
        foreach (var val in new RangeEnumerable(1, 10))
        {
            Console.WriteLine("Value:{0}", val);
        }

        //非ジェネリックでの列挙処理
        System.Collections.IEnumerable enumerable = (System.Collections.IEnumerable)new RangeEnumerable(11, 10);
        foreach (int val in enumerable)
        {
            Console.WriteLine("Value:{0}", val);
        }

        //IEnumerable<T>を返すメソッドでの列挙処理
        foreach (var val in new RangeEnumerable2(20, 10, 3).GetEnumerable())
        {
            Console.WriteLine("Value:{0}", val);
        }
    }
}