匿名メソッド (C# プログラミング ガイド)
更新 : 2007 年 11 月
C# 2.0 より前のバージョンでは、デリゲートを宣言するには名前付きメソッドを使用するしかありませんでした。C# 2.0 では匿名メソッドが導入され、C# 3.0 以降では、インライン コードを記述するための本来の方法として、匿名メソッドに代わってラムダ式が使用されるようになりました。ただし、このトピックに記載した匿名メソッドに関する情報は、ラムダ式にも適用されます。ラムダ式にはない機能を匿名メソッドが備えているケースが 1 つあります。匿名メソッドではパラメータ リストを省略することができます。これは、匿名メソッドをさまざまなシグネチャを持つデリゲートに変換できることを意味します。これはラムダ式ではありえません。特にラムダ式に関する詳細については、「ラムダ式 (C# プログラミング ガイド)」を参照してください。
匿名メソッドは、基本的にコード ブロックをデリゲート パラメータとして渡すために作成します。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 instance
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();
}
解説
匿名メソッドのパラメータのスコープは、匿名メソッド ブロックです。
匿名メソッド ブロックの内部で使用しているジャンプ ステートメント (goto、break、continue など) のジャンプ先がブロックの外部にある場合はエラーになります。また、匿名メソッド ブロックの外部で使用しているジャンプ ステートメント (goto、break、continue など) のジャンプ先がブロックの内部にある場合もエラーになります。
匿名メソッドの宣言をスコープに含むローカル変数とパラメータは、匿名メソッドの外部変数と呼ばれます。たとえば、次のコード セグメントに示されている 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()
{
// Instatiate 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.
*/
参照
概念
参照
unsafe コードとポインタ (C# プログラミング ガイド)
名前付きメソッドを使用したデリゲートと匿名メソッドを使用したデリゲート (C# プログラミング ガイド)