none
匿名メソッドをその場で実行する方法はあるか RRS feed

  • 質問

  • C# 2.0 での質問です。

     

    匿名メソッドを変数や引数に入れずに、その場で実行する方法はあるでしょうか。

     

    簡単な例で示すと、次のような感じです。

     

    Code Snippet
    float a = (delegate() { return 0.3f; })();

      

    もちろんこれは構文エラー(メソッド名が必要)ですが、こんな感じで a に 0.3f が代入できるような方法はあるでしょうか。

    2007年7月16日 7:38

回答

  • デリゲート型の new 式の中で、メソッド名の代わりに匿名メソッドを使用することはできますが。

    // 変数に代入したいのならともかく直接呼び出す必然性がよくわかりません。

    2007年7月16日 7:55
  •  豊田 芳彰 さんからの引用
     

     

    Code Snippet
    float a = (delegate() { return 0.3f; })();

      

    もちろんこれは構文エラー(メソッド名が必要)ですが、こんな感じで a に 0.3f が代入できるような方法はあるでしょうか。

    例えば事前にデリゲート型を

    delegate float GetFloatValue();

    のように宣言しておけば、

    float a = (float)(new GetFloatValue(delegate() { return 0.3f; }).DynamicInvoke());

    とかでできると思いますが、何のために何がしたいのかよくわかりません。
    2007年7月16日 8:17

すべての返信

  • デリゲート型の new 式の中で、メソッド名の代わりに匿名メソッドを使用することはできますが。

    // 変数に代入したいのならともかく直接呼び出す必然性がよくわかりません。

    2007年7月16日 7:55
  •  豊田 芳彰 さんからの引用
     

     

    Code Snippet
    float a = (delegate() { return 0.3f; })();

      

    もちろんこれは構文エラー(メソッド名が必要)ですが、こんな感じで a に 0.3f が代入できるような方法はあるでしょうか。

    例えば事前にデリゲート型を

    delegate float GetFloatValue();

    のように宣言しておけば、

    float a = (float)(new GetFloatValue(delegate() { return 0.3f; }).DynamicInvoke());

    とかでできると思いますが、何のために何がしたいのかよくわかりません。
    2007年7月16日 8:17
  • お返事ありがとうございます。

     

    必然性があるかと問われれば、全くないです。他の方法で代用できるので。場合によっては(私にとって)便利だという程度で、そんなに深い意味はないです。たまにですが、Lisp や Scheme ならもっとスマートに記述できそうだなぁと思う時があるので。

     

    Code Snippet
    float a = (float)(new GetFloatValue(delegate() { return 0.3f; }).DynamicInvoke());

     

    ここまで余計な記述が含まれると、本質を見失って意味がなくなりますね。

     

    簡単に記述できる方法は無さそうなので諦めます。ありがとうございました。

    2007年7月16日 8:23
  • 豊田さんこんにちは。

    C#3.0ではlambda式が追加されます。

    Lispまで柔軟な書き方はできませんが、よりスマートな書き方が出来るようになるみたいですよ。

    仕様書読んだのだいぶ昔なので書き方があっているかちょっと自信がありませんが、

    (int a) => a + 1;

    みたいな感じに書けたかと思います。

    これをLispで書くと

    (lambda (a) (+ a 1))

    こんな感じでしょうか。

    内部的にはコンパイラがデリゲートに展開してくれているのだと思いますが。

     

    3.0では他にも面白そうな拡張がありますし、今後関数型言語に特化(?)していくと設計者の方が言っておられたので、

    個人的に楽しみです。(^^

    2007年7月16日 15:57
  •  豊田 芳彰 さんからの引用

    必然性があるかと問われれば、全くないです。他の方法で代用できるので。場合によっては(私にとって)便利だという程度で、そんなに深い意味はないです。たまにですが、Lisp や Scheme ならもっとスマートに記述できそうだなぁと思う時があるので。

     

    例がまずいかと. 

    Code Snippet

    float a1 = 0.3f;

    float a2 = ((Func<float>)delegate() { return 0.3f; })(); // C# 2.0 + Func<T>

    float a3 = ((Func<float>)(() => 0.3f))(); // C# 3.0

    float a4 = ((Func<float>)(() => { return 0.3f; }))(); // C# 3.0

     

    少なくともこの例は「スマートに記述できている」という場面ではなさそうな気がします.同じ処理内容で一番短いのは a1 ですし.

    実際に「あったら便利だ」と思える状況を例に出した方が良いかもしれません.

     

    無理矢理例を作るとすれば,たとえばC#のifやswitchを関数的に使いたいときなどでしょうか.三項演算子を連ねるぐらいならifやswitchで書きたいと.

    Code Snippet
    string FizzBuss = ((Func<int, string>)(delegate(int i)
    {
        if (i % 3 == 0) return "Fizz";
        else if (i % 5 == 0) return "Buzz";
        else if (i % 15 == 0) return "FizzBuzz";
        else return i.ToString();
    }))(10); // C# 2.0 + Func<T, TResult>

     

    とはいえ,C# 2.0/3.0の得意分野としては,1)まずパイプラインを作って,2) そこにデータを流し込む (IEnumerable) ですので,即時評価する文法の拡張としてラムダ式や匿名メソッドを使いたい場面はやはり少ないような気がします.

    2007年7月17日 2:05