共通型システムのデリゲート
更新 : 2007 年 11 月
ランタイムは、C++ の関数ポインタと類似の目的で使用される、デリゲートと呼ばれる参照型をサポートしています。関数ポインタとは異なり、デリゲートは安全で、検証可能で、タイプ セーフです。デリゲート型は、互換性のあるシグネチャで任意のメソッドを表すことができます。関数ポインタは静的関数しか表すことができませんが、デリゲートは静的メソッドとインスタンス メソッドの両方を表すことができます。デリゲートは、.NET Framework のイベント ハンドラとコールバック関数に使用されます。
メモ : |
---|
共通言語ランタイムはグローバル メソッドのシリアル化をサポートしないため、デリゲートを使用して他のアプリケーション ドメインでグローバル メソッドを実行できません。 |
すべてのデリゲートが MulticastDelegate を継承し、System.MulticastDelegate は Delegate を継承します。C#、Visual Basic、および C++ 言語はこれらの型からの継承を許可せず、代わりにデリゲートを宣言するためのキーワードを提供します。
共通言語ランタイムには、継承されたメソッドに加えて、BeginInvoke および EndInvoke というデリゲート型用の 2 つの特別なメソッドが用意されています。これらのメソッドの詳細については、「同期メソッドの非同期呼び出し」を参照してください。
デリゲートは MulticastDelegate を継承するため、デリゲートには呼び出しリストがあります。これは、デリゲートが表し、デリゲートが呼び出されたときに実行されるメソッドのリストです。リストのすべてのメソッドは、デリゲートが呼び出されたときに指定される引数を受け取ります。
メモ : |
---|
デリゲートに戻り値が含まれていても、呼び出しリストに複数のメソッドが含まれているデリゲートに対しては、戻り値は定義されません。 |
デリゲートの作成と使用
コールバック メソッドなど、多くの場合、デリゲートは 1 つのメソッドのみを表すため、デリゲートを作成しそれを呼び出す以外の処理は必要ありません。
複数のメソッドを表すデリゲートの場合、.NET Framework は Delegate と MulticastDelegate デリゲート クラスのメソッドを提供し、デリゲートの呼び出しリスト (Delegate.Combine メソッド) にメソッドを追加したり、メソッド (Delegate.Remove メソッド) を削除したり、呼び出しリスト (Delegate.GetInvocationListメソッド) を取得したりする操作をサポートしています。
メモ : |
---|
C#、C++、および Visual Basic では、イベント ハンドラの追加や削除に使用する構文が用意されているため、イベント ハンドラ デリゲートに対して、これらのメソッドを使用する必要はありません。 |
閉じている静的デリゲートと開いているインスタンス デリゲート
デリゲートは static (Visual Basic の Shared) またはインスタンス メソッドを表すことができます。通常、デリゲートがインスタンス メソッドを表すとき、インスタンスはメソッドと共にデリゲートにバインドされます。たとえば、イベント ハンドラ デリゲートの呼び出しリストには、メソッドが属するオブジェクトをそれぞれ参照する 3 つのインスタンス メソッドが含まれている可能性があります。
.NET Framework Version 2.0 では、インスタンス メソッドに対してオープン デリゲートを作成することもできます。インスタンス メソッドには暗黙のインスタンス パラメータ (C# では this、Visual Basic では Me によって表されます) が含まれ、この隠しパラメータを公開するデリゲート型によって表すことができます。つまり、デリゲート型には、仮パラメータ リストの先頭に、メソッドが属するクラスと同じ型の余分なパラメータが含まれています。これと逆の場合もサポートされるため、静的メソッドの最初の引数をバインドすることもできます。
メモ : |
---|
開いているインスタンスと閉じている静的デリゲートの作成は、Visual Basic、C++、または C# のデリゲート コンストラクタでは直接サポートされていません。代わりに、MethodInfo オブジェクトを指定する Delegate.CreateDelegate(Type, Object, MethodInfo, Boolean) などの Delegate.CreateDelegate メソッド オーバーロードの 1 つを使用してください。 |
デリゲート バインドのための緩和された規則
.NET Framework Version 2.0 では、デリゲートのパラメータ型と戻り値の型は、デリゲートが表すメソッドのパラメータ型および戻り値の型と互換性を持つ必要がありますが、型が正確に一致する必要はありません。
メモ : |
---|
.NET Framework Version 1.0 と 1.1 では、型は正確に一致する必要があります。 |
デリゲート パラメータの型の制限がメソッド パラメータの型より多い場合、デリゲートに渡される引数がメソッドに安全に渡されることが保証されるため、デリゲートのパラメータとメソッドの対応するパラメータには互換性があります。
同様に、メソッドの戻り値の型の制限がデリゲートの戻り値の型より多いと、メソッドの戻り値がデリゲートの戻り値の型に安全にキャストされることが保証されるため、デリゲートの戻り値の型とメソッドの戻り値の型には互換性があります。
たとえば、Hashtable 型のパラメータおよび Object の戻り値の型を持つデリゲートは、Object 型のパラメータおよび Hashtable 型の戻り値でメソッドを表すことができます。
コード例および詳細については、「Delegate.CreateDelegate(Type, Object, MethodInfo)」を参照してください。
デリゲートと非同期メソッド呼び出し
すべてのデリゲートには、非同期的にデリゲートを呼び出すことのできる BeginInvoke メソッドおよび後でリソースをクリーンアップする EndInvoke メソッドが含まれています。これらのメソッドは、各デリゲート型に対して自動的に生成されます。BeginInvoke メソッドを使用してデリゲートが呼び出される場合、デリゲートが表すメソッドは ThreadPool に属するスレッド上で実行されます。
コード例および詳細については、「デリゲートを使用した非同期プログラミング」を参照してください。