エラー処理で行いがちな、条件判定ブロックを整理する

エラー判定を行うときに、簡単に書いてしまうと下記の記述になることがあります。

            int a = 5;
            int b = 10;

            if (a == b) {
                Console.WriteLine("一致ダメ");
                return;
            }

            if (a > b) {
                Console.WriteLine("aが大きくてはダメ");
                return;
            }

            if (b > a * 10) {
                Console.WriteLine("bが大きすぎてもダメ");
                return;
            }

return;が入っていることから、これはこれ以上まとめようがないと思っていました。
ただこれをじっと見ていたら、次のまとめ方に気づきました。

            var 確認事項 = new List<Tuple<bool, string>>{
                Tuple.Create((a==b),"一致ダメ"),
                Tuple.Create((a>b),"aが大きくてはダメ"),
                Tuple.Create((b > a * 10),"bが大きすぎてもダメ"),
            };

            foreach (var s in 確認事項) {
                if (s.Item1) {
                    Console.WriteLine(s.Item2);
                    return;
                }
            }

ここで、次のネタが発生します。
aとbの大小関係を評価するタイミングはどこなのか? というネタです。
上記の例では、変数への代入時ですので、この後a,bの値が変更になるコードの場合には、意図した動作にはなりません。

そういったケースでは次の書き換えを行います。

            var 確認事項2 = new List<Tuple<Func<bool>, string>>{
                Tuple.Create((Func<bool>)(()=>a==b),"一致ダメ"),
                Tuple.Create((Func<bool>)(()=>a>b),"aが大きくてはダメ"),
                Tuple.Create((Func<bool>)(()=>b > a * 10),"bが大きすぎてもダメ"),
            };

            foreach (var s in 確認事項2) {
                if (s.Item1()) {
                    Console.WriteLine(s.Item2);
                    return;
                }
            }

ラムダ式の評価タイミングが意図したタイミングに合うと思います。
ちょっと定義部分の記述が多すぎるので、簡潔にしたいところです。
同様のパターンで条件判定の後に異なる動作を入れる場合は、stringの部分をラムダ式にしてしまえば実現できます。

  1. No Comments