匿名メソッド (C# プログラミング ガイド)

C# 2.0 より前のバージョンでは、デリゲートを宣言するには名前付きメソッドを使用するしかありませんでした。 C# 2.0 では匿名メソッドが導入され、C# 3.0 以降では、インライン コードを記述するための本来の方法として、匿名メソッドに代わってラムダ式が使用されるようになりました。 ただし、このトピックに記載した匿名メソッドに関する情報は、ラムダ式にも適用されます。 ラムダ式にはない機能を匿名メソッドが備えているケースが 1 つあります。 匿名メソッドではパラメーター リストを省略できます。 これは、匿名メソッドをさまざまなシグネチャを持つデリゲートに変換できることを意味します。 これはラムダ式ではありえません。 特にラムダ式に関する詳細については、「ラムダ式」を参照してください。

匿名メソッドは、基本的にコード ブロックをデリゲート パラメーターとして渡すために作成します。 2 つの例を次に示します。

// Create a handler for a click event.
button1.Click += delegate(System.Object o, System.EventArgs e)
                   { System.Windows.Forms.MessageBox.Show("Click!"); };
// Create a delegate.
delegate void Del(int x);

// Instantiate the delegate using an anonymous method.
Del d = delegate(int k) { /* ... */ };

匿名メソッドを使用すると、別のメソッドを作成する必要がないため、デリゲートをインスタンス化する際のコーディングのオーバーヘッドを削減できます。

たとえば、デリゲートの代わりにコード ブロックを指定すると、メソッドを作成するのが余分なオーバーヘッドと思われる場合に役立つことがあります。 新しいスレッドを開始する場合などがそのよい例です。 このクラスではスレッドを作成し、スレッドが実行するコードも含みますが、デリゲート用の追加のメソッドは作成していません。

void StartThread()
{
    System.Threading.Thread t1 = new System.Threading.Thread
      (delegate()
            {
                System.Console.Write("Hello, ");
                System.Console.WriteLine("World!");
            });
    t1.Start();
}

解説

匿名メソッドのパラメーターのスコープは、匿名メソッド ブロックです。

匿名メソッド ブロックの内部で使用しているジャンプ ステートメント (gotobreakcontinue など) のジャンプ先がブロックの外部にある場合はエラーになります。 また、匿名メソッド ブロックの外部で使用しているジャンプ ステートメント (gotobreakcontinue など) のジャンプ先がブロックの内部にある場合もエラーになります。

匿名メソッドの宣言をスコープに含むローカル変数とパラメーターは、匿名メソッドの外部変数と呼ばれます。 たとえば、次のコード セグメントに示されている n は外部変数です。

int n = 0;
Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };

外部変数への参照nと呼ばれますキャプチャ 、デリゲートを作成します。 匿名メソッドを参照するデリゲートがガベージ コレクションの対象にされるまでローカル変数とは異なり、キャプチャされた変数の有効期間を拡張します。

匿名メソッドは、外部スコープの ref パラメーターや out パラメーターにアクセスできません。

匿名メソッド ブロック内のアンセーフ コードにはアクセスできません。

匿名メソッドは、is 演算子の左辺では使用できません。

使用例

次の例は、デリゲートをインスタンス化する 2 つの方法を示しています。

  • デリゲートと匿名メソッドを関連付ける。

  • デリゲートと名前付きメソッド (DoWork) を関連付ける。

どちらの場合も、デリゲートを呼び出すと、メッセージが表示されます。

// Declare a delegate.
delegate void Printer(string s);

class TestClass
{
    static void Main()
    {
        // Instantiate the delegate type using an anonymous method.
        Printer p = delegate(string j)
        {
            System.Console.WriteLine(j);
        };

        // Results from the anonymous delegate call.
        p("The delegate using the anonymous method is called.");

        // The delegate instantiation using a named method "DoWork".
        p = new Printer(TestClass.DoWork);

        // Results from the old style delegate call.
        p("The delegate using the named method is called.");
    }

    // The method associated with the named delegate.
    static void DoWork(string k)
    {
        System.Console.WriteLine(k);
    }
}
/* Output:
    The delegate using the anonymous method is called.
    The delegate using the named method is called.
*/

参照

C# リファレンス
C# プログラミング ガイド
デリゲート
ラムダ式
unsafe コードとポインター
メソッド
名前付きメソッドを使用したデリゲートと匿名メソッドを使用したデリゲート