Interactive Extensionsを自分で実装する – 4.Case

Interactive Extensions(Ix)を自分で実装する、第4回はCaseです。

使い方・出力の順に見ていきましょう、このCaseもオーバーロードがあります。まずは2つの引数を取るほうから。

static void CaseTest1()
{
    var sources = new Dictionary<int, IEnumerable<int>>
    {
        {3, Enumerable.Range(1,20).Where(a => a%3==0)}, // 3, 6, 9, ..
        {1, Enumerable.Range(1,20).Where(a => a%3==1)}, // 1, 4, 7, ..
        {2, Enumerable.Range(1,20).Where(a => a%3==2)}, // 2, 5, 8, ..
    };

    for (int i = 0; i <= 3; i++){
        var sequence = EnumerableEx.Case(() => i, sources);
        foreach (var item in sequence){
            Console.Write(item);
        }
        Console.WriteLine();
    }
}

case_1

Caseというメソッドの通り、Switch-CaseのあのCaseです。IEnumerable<T>のDictionaryを引数に取り、その中からどれにしようかな..と決めるわけです。ここではi=0の初期値でDictionaryにないキーを取るようにしています。通常のDictionaryはない値を参照すると例外がスローされますが、Caseでは例外がスローされず空のシーケンスが渡されます。

続いてもう1つのCaseメソッド、こちらは先ほどに加えてもう1つ追加の引数を取ります。

static void CaseTest2()
{
    var sources = new Dictionary<int, IEnumerable<int>>
    {
        {3, Enumerable.Range(1,20).Where(a => a%3==0)}, // 3, 6, 9, ..
        {1, Enumerable.Range(1,20).Where(a => a%3==1)}, // 1, 4, 7, ..
        {2, Enumerable.Range(1,20).Where(a => a%3==2)}, // 2, 5, 8, ..
    };
    var defaultSource = Enumerable.Range(1, 10);

    for (int i = 0; i <= 3; i++){
        var sequence = EnumerableEx.Case(() => i, sources, defaultSource);
        foreach (var item in sequence){
            Console.Write(item);
        }
        Console.WriteLine();
    }
}

case_2

こちらはDictionaryに指定したキーが存在しなかった場合にデフォルトシーケンスを返すよう指定することが可能です。

それでは実装してみましょう。(Let’s Implement It!)

Case…複数のシーケンスの中から条件にあうシーケンスを返す。

namespace EmulateInteractiveExtensions
{
    public static class EmulateIxExtensions
    {
        public static IEnumerable<TResult> Case<TValue, TResult>(Func<TValue> selector,
                                                                 IDictionary<TValue, IEnumerable<TResult>> sources)
        {
            // 存在しない場合も例外は投げず空のIEnumerable<TResult>を返す。
            return Case(selector, sources, Enumerable.Empty<TResult>());
        }
        public static IEnumerable<TResult> Case<TValue, TResult>(Func<TValue> selector,
                                                                 IDictionary<TValue,IEnumerable<TResult>> sources,
                                                                 IEnumerable<TResult> defaultSource)
        {
            // defaultSourceは使用如何によらずnullチェック対象
            if (selector == null || sources == null || defaultSource == null){
                throw new ArgumentNullException();
            }

            TValue key = selector();
            if (sources.ContainsKey(key)){
                return sources[key];
            }
            return defaultSource;
        }
    }
}

コメントを残す

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

WordPress.com ロゴ

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

Twitter 画像

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

Facebook の写真

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

Google+ フォト

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

%s と連携中