Interactive Extensionsを自分で実装する – 5.Defer, Create

Interactive Extensions(Ix)を自分で実装する、第5回目はDeferです。

ディファー…. レント?(Different)と捉えられる方がいるかと思いますが、Deferは「引き延ばす」という意味です。実際に列挙されるまで確定を引き延ばすために用います。

public static IEnumerable<TResult> Defer<TResult>(Func<IEnumerable<TResult>> enumerableFactory);

使い方は以下のような感じです。

private static IEnumerable<int> GetSequence(){
    yield return 3;
    yield return 5;
    yield return 17;
}
private static void DeferTest(){
    Func<IEnumerable<int>> func = GetSequence;
    var result = EnumerableEx.Defer(func);
    foreach(var item in result){
        Console.Write(item);
    }
}

defer

シーケンスを出力するメソッドを作って評価タイミングでその関数を呼び出すという考えです。上のコード、「GetSequence()なんて作らず」ラムダ式でまとめちゃおぅ、私もそう思いましたがラムダ式・匿名メソッドの中でyieldは使えないとのこと。はじめて知りました。

それでは実装。(Let’s Implement It!)

Defer…渡されたシーケンスの列挙を遅らせる。

namespace EmulateInteractiveExtensions
{
    public static class EmulateIxExtensions
    {
        public static IEnumerable<TResult> Defer<TResult>(Func<IEnumerable<TResult>> enumerableFactory)
        {
            if (enumerableFactory == null){
                throw new ArgumentNullException();
            }
            return enumerableFactory();
        }
    }
}

何か間違っていないか若干不安です;

 

続いてCreate。Deferに似ていますが、Createのシグネチャはこちら。

public static IEnumerable<T> Create<T>(Func<IEnumerator<T>> getEnumerator);

使い方はこんな感じ。IEnumeratorとか普段実装しないので手抜きです。

static void CreateTest()
{
    Func<IEnumerator<int>> creator = () => Enumerable.Range(1, 10).GetEnumerator();
    var result = EmulateIxExtensions.Create(creator);
    foreach (var item in result)
    {
        Console.WriteLine(item);
    }
}

create

それでは実装です。(Let’s Implement It!)

Create…IEnumeratorからIEnumerableをつくる

namespace EmulateInteractiveExtensions
{
    public static class EmulateIxExtensions
    {
        public static IEnumerable<T> Create<T>(Func<IEnumerator<T>> getEnumerator)
        {
            if (getEnumerator == null){
                throw new ArgumentNullException();
            }

            var enumerator = getEnumerator();
            while (enumerator.MoveNext())
            {
                yield return enumerator.Current;
            }
        }
    }
}

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中