2011-02-07 9 views
10

私は、なぜコードの一部がコンパイルに失敗し、他のコンパイルがうまくいくのかという良い説明を探しています。ラムダステートメントのまわりのかっこで構文エラーが発生するのはなぜですか?

の失敗:

richTextBox1.Invoke(new MethodInvoker((() => { richTextBox1.AppendText("test"); }))); 

がエラーに

メソッド名を与えます右MethodInvoker(後の括弧に

を期待。どうやら、私はラムダステートメントをかっこで囲むことはできません。

コンパイル:

richTextBox1.Invoke(new MethodInvoker(() => { richTextBox1.AppendText("test"); })); 

質問がある - なぜですか?

ラムダ式ではそうではないことがわかっていれば、括弧で任意のメソッドパラメータをラップすることができるとはいつも思っていました。私は彼らが幾分特別であることを理解していますが、私はまだこれに正当な理由は見当たりません。たぶん私は構文について何かを理解していないかもしれません。私は本当にそれを取得したいと思います。

ちなみに、これはVS2008、.NET 3.5 SP1で、VS2010と.NET 4ではまだテストされていません。

答えて

7

を呼び出すことができますが、それが含まれている括弧で囲まれた式ですラムダ式。したがって、このメソッド呼び出しの抽象構文ツリー内のこのパラメータのノードは、仕様で必要とされるラムダ式ではなく、カッコで囲まれた式になります。これが理由です。

Microsoft C#コンパイラが仕様に違反していて、(仕様通りではありませんが)そのような表現を受け入れない場所もありますが、これはその1つではありません。

仕様の該当するセクションは6.5です。

+0

ありがとうございます。好奇心の外に - そのような場所の例を教えてください。 – Dyppl

+3

@Dyppl: 'Func F(){return(()=> 1); } 'は合法ですが、仕様に従ってはいけません。 – jason

+0

ありがとう!さて、私の質問については少し気分が良くなりました。そのような矛盾はあなたの頭の中で最終的に混乱するでしょう – Dyppl

3

Invoke()メソッド内には()=>{}があり、最初の例ではそれが見つからないため、コンパイラはこれを認識しません。括弧内のすべてが最初に評価され、単一のオブジェクトが返されます。この場合、コンパイラはデリゲートへの参照を期待します。私は、この拡張メソッドと同じ問題が解決した

編集:

public delegate void EmptyHandler(); 
    public static void SafeCall(this Control control, EmptyHandler method) 
    { 
     if (control.InvokeRequired) 
     { 
      control.Invoke(method); 
     } 
     else 
     { 
      method(); 
     } 
    } 

は、だからそれはラムダ式ではありません

RichTextBox rtb = new RichRextBox(); 
... 

rtb.SafeCall(()=> rtb.AppendText("test")); 
+3

実際には、匿名の参加者はまた、シンタックスシュガーです。 C#コンパイラはラムダ構文を匿名デリゲート構文に変換していません。両方を具体的な関数(またはクロージャに応じて関数を持つクラス)と従来の代理人に変換します。 –

4

あなたは「メソッドパラメータ」を書いたと誤解されています。作成したコンストラクトはメソッド呼び出しではなく、デリゲート作成式(C#仕様、セクション7.6.10を参照)を作成しました。5)、メソッド基、

  • 匿名関数または
  • 動的コンパイル時の型またはデリゲート型のいずれかの値

    • のいずれかでなければならない1つの引数を持つことが想定されています。あなたのケースでは

    それは「どこかの内部では、」無名関数を含む式であるから、それはメソッドグループ(エラーメッセージはメソッド名がが期待されていることをほのめかしている)、また匿名関数(ではありません)、前記タイプの値も含まない。

    あなたは、メソッドinvokationを書いた場合、あなたは、確かに、それはラムダ式が含まれている場合でも、括弧内のパラメータをラップすることができます:

    void Method(Action action) 
    { 
    } 
    ... 
    Method((() => { Console.WriteLine("OK"); })); 
    
  • 関連する問題