2005年C#の旅その2

今回は匿名メソッドについて見てみたいと思います。匿名メソッドを使うと処理のブロックをメソッドの引数として渡すことが出来るので、ほとんど同じだけど一部だけ異なるメソッドとかで威力を発揮します。また、delegateも使いやすく改善され、また、パフォーマンスも良くなっている(まだテストしてませんが、そのはず)ので、ガンガン使っていきたいところです。

using System;

class Program
{
    delegate void Hello();
    delegate int Func(int n);

    static void SayHello()
    {
        Console.WriteLine("Hello");
    }

    static int Apply(Func fn, int arr) {
        int ret = 0;
        foreach (int n in arr)
            ret += fn(n);
        return ret;
    }

    static void Main(string args)
    {
        int cnt = 0;

        // 匿名メソッド。
        Hello m = delegate() { Console.WriteLine("Hello, World! {0}", cnt++); };
        // ローカル関数のように呼び出す
        m();
        m();
        // 匿名メソッドブロック外の変数にもアクセス出来るのでcntは2となっている。
        Console.WriteLine("cnt = {0}", cnt);

        // C#1.0ならm = new Hello(SayHello);と書く必要があったが、
        // C#2.0ではそのまま代入出来る
        m = SayHello;
        m();

        // 配列に対して第一引数の関数を適用した結果の合計を求める
        int arr = new int { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        // 1〜10の和
        Console.WriteLine("Σx = {0}", Apply(delegate(int n) { return n; }, arr));
        // 1〜10の二乗の和
        Console.WriteLine("Σx^2 = {0}", Apply(delegate(int n) { return n*n; }, arr));

        Console.ReadLine();
    }
}

/* 結果
Hello, World! 0
Hello, World! 1
cnt = 2
Hello
Σx = 55
Σx^2 = 385 */

delegateはイチイチnew EventHandlerとかしなくても良くなったのが嬉しいです。あと、C#ではローカル関数をサポートしていませんが、匿名メソッドを使うと、それっぽいことが出来ますね。

ところで、VS.NET2003までだとデバッグ無しで実行するとコンソールが表示されて止まったのですが、VS2005ですと、コンソールが閉じてしまうため、Console.ReadLine();とかしないと駄目になってちょっと面倒。なんかやり方があるのかな?