忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

C#でRubyっぽいループを書く

(この記事を書き終わってもしやと思いググッてみると
どうやら同じことを考えている人がすでに居たようです。残念)


4,5年前Rubyを使ったことがあったのですが、
ループがけっこう簡単です。
5.times { |i|
	puts i
}
Rubyを使ったことのない方のために言うと、
上の実行結果は
0
1
2
3
4

です。

これはたぶんC#よりも初学者にとって分かりやすいと思います。
なにせ「5回繰り返せ!」というのが
5.timesからぐっと伝わってくるからです。
(そう思いませんか!?)

私が初めて覚えたプログラミング言語はCでしたが、
当時中学生の身としてforはいささか複雑すぎました。
結果forに引っかかったことを覚えています。

C#でクロージャを使ってループ

しかしここで言いたいのはC#はダメだということではありません!
C#でもRubyのような書き方ができるからです。

まずC#で普通にループを書こうと思えば
以下のようにforを使います。
class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 5; i++)
        {
            System.Console.WriteLine(i);
        }
    }
}


結果は、上に書いたrubyのコードと同じです。
数字を0から4まで出力します。

C#でRubyのように書くにはどうすればいいでしょう?
ここで拡張メソッドの登場です。

static class Int32Extension
{
    public static void Times(this int loopCount, System.Action<int> loop)
    {
        for (int i = 0; i < loopCount; i++)
        {
            loop(i);
        }
    }
}


皆さんご存知のとおり上のように書くと、
System.Int32構造体に拡張メソッドを追加できます。
つまり以下のようにかけるのです。
class Program
{
    static void Main(string[] args)
    {
        5.Times(i => System.Console.WriteLine(i));
    }
}

いかがでしょうか。
forを使うよりシンプルになっているのは確かです。

ただ・・・これは良いものなのでしょうか悪いものなのでしょうか?
なるほどシンプルで書きやすいというのはそのとおりでしょうが、
forより明らかにパフォーマンスが落ちそうです。
もっともパフォーマンスはネックになるところ以外では気にするべきではありません。

では読みやすさはどうでしょうか?
個人的にこれを使ってみて、
「書きやすいけれどももしかするとほんの少し読みにくいかもしれない」
といった感想です。
読みにくいかもしれないというのはデリゲートに{}を使ったとき);と重なって
ちょっと汚く見えるかもしれないということです。

ただ、Timesの他にもUpToメソッドなどを書いて使ってみたのですが
そちらは});がごちゃごちゃしているのを差し引いても
かなり読みやすくなったと思います。

個人的見解としては、今後もループをたくさん使わなければいけないときにはこれを使うと思います、
といったところでしょうか。

拍手[0回]

PR