2009年11月01日

【yield】 foreach可能なクラスを作るには?

今日からは、また新しい章に入ります。
今回はyield return文について解説します。
yield returnを使用することで、foreachで列挙可能な自前のクラスを作ることが出来ます。

Q. foreachで列挙可能なクラスを作るには?
A. IEnumerator<T>を返す、GetEnumeratorという名前のメソッドを作る
これだけです。interfaceは実装しなくても良いみたいです。

では、IEnumerator<T>型とは何者なのか?
この型が今回解説するyield returnと深い関係にあります。
yield returnとはreturnが付いてる事から分かるように、戻り値を返す文です。
ただし、若干普通の処理の流れとは違う部分があるので、慣れが必要です。
以下のコードを御覧ください。
class EnumerableClass
{
    public IEnumerator<int> GetEnumerator()
    {
        Console.WriteLine("チェックポイント1");
        yield return 1;

        Console.WriteLine("チェックポイント2");
        yield return 2;

        Console.WriteLine("チェックポイント3");
        yield return 3;
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 列挙可能なオブジェクト
        var enumerable = new EnumerableClass();
        foreach (int ret in enumerable)
        {
            Console.WriteLine("foreach {0}周目の戻り値", ret);
        }

        // <結果>
        // チェックポイント1
        // foreach 1周目の戻り値
        // チェックポイント2
        // foreach 2周目の戻り値
        // チェックポイント3
        // foreach 3周目の戻り値
    }
}
EnumerableClassがforeach可能なクラスです。
foreachでGetEnumerator()をコールしますが、yield return 1;まで実行したとこで一旦処理がMainメソッドに戻り、foreach内の処理が1回実行されます。
次に呼ばれた時は、前回yield returnした箇所の続きから実行することになります。(2周目はyield return 2;まで実行)
foreach1周毎に次のyield returnまで実行するということですね。
foreachとGetEnumerator()を交互に実行しているイメージを持つと分かりやすいかと思います。

処理の流れが掴み辛いですが、自前でforeach可能な文が手軽に作れるというのは結構便利です。
次回は、もう少し実践的で使えそうなサンプルコードを考えてみたいと思います。
タグ:yield
posted by 吾一 at 21:48| 4. yield return | このブログの読者になる | 更新情報をチェックする
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。