コールバック関数は Windows プログラミングの重要な部分です。 C または C++ プログラミングの経験がある場合は、多くの Windows API でコールバックを使用したことがあります。 AddressOf キーワードを VB に追加すると、開発者や開発者は、かつては制限されていた API を利用できるようになります。コールバック関数は実際にはメソッド呼び出しへのポインターであり、関数ポインターとも呼ばれ、非常に強力なプログラミング機能です。 .NET は、関数ポインターの概念をデリゲートの形式で実装します。これらの特別な点は、C 関数ポインターとは異なり、.NET デリゲートはタイプセーフであることです。これは、C の関数ポインタが記憶ユニットへの単なるポインタであることを示しており、パラメータや戻り値の型はもちろん、このポインタが実際に何を指しているのかもわかりません。この章で説明するように、.NET デリゲートはタイプ セーフな操作として動作します。以下では、.NET がイベントを実装する方法としてデリゲートをどのように使用するかを学習します。
1. 委託
メソッドを別のメソッドに渡したい場合は、デリゲートを使用する必要があります。それらの意味を理解するには、次のコードを見てください。
int i = int.Parse("99");
上の例に示すように、私たちはデータをパラメータとしてメソッドに渡すことに慣れています。したがって、別のメソッドをメソッドに渡すのは少し奇妙に思えます。メソッドによって実行される操作がデータに対して実行されるのではなく、より複雑な別のメソッドに対して実行される場合があります。 2 番目のメソッドが何であるかはコンパイル時にわかりません。この情報は実行時にのみ取得できるため、2 番目のメソッドをパラメータとして最初のメソッドに渡す必要があります。これは、いくつかの例を示します。 :
1. スレッドの開始-----C# では、特定の新しい実行シーケンスを並行して実行するようにコンピューターに指示できます。このシーケンスはスレッドと呼ばれます。スレッドの実行を開始するには、蓄積された System.Threading.Thread のインスタンスで Start() メソッドを使用します。新しい実行シーケンスを開始するようにコンピューターに指示したい場合は、シーケンスが実行される場所を指定する必要があります。コンピュータには、実行を開始するメソッドの詳細が提供される必要があります。つまり、Thread.Start() メソッドは、スレッドによって呼び出されるメソッドを定義するパラメータを受け取る必要があります。
2. 一般ライブラリ クラス-----さまざまな標準タスクを実行するコードを含むライブラリが多数あります。これらのライブラリは通常、自己完結型です。このようにして、ライブラリを作成するときに、タスクの実行方法がわかります。ただし、タスクにサブタスクが含まれる場合もあります。ライブラリを使用するクライアント コードのみが、これらのサブタスクの実行方法を知っています。たとえば、オブジェクトの配列を取得して昇順に並べ替えるクラスを作成します。ただし、並べ替えプロセスの一部には、配列内の 2 つのオブジェクトを再利用し、それらを比較してどちらが先に来るかを確認することが含まれます。オブジェクトの配列を並べ替えることができるクラスを作成する場合、オブジェクトをどのように比較するかを事前にコンピューターに指示することはできません。クラス内のオブジェクトの配列を処理するクライアント コードは、並べ替えるオブジェクトを比較する方法をクラスに指示する必要もあります。言い換えれば、クライアント コードは、これを適切にする特定の詳細をクラスに渡す必要があります。
3. イベント ------- 通常、どのようなイベントが発生したかをコードに通知します。 GUI プログラミングは主にイベントの処理に関するものです。イベントが発生すると、ランタイムはどのメソッドを実行する必要があるかを認識する必要があります。これには、時刻をデリゲートのパラメーターとして処理するメソッドを渡す必要があります。これらについては後で説明します。
以前に、メソッド名が引数として他のメソッドに渡される場合があるというルールを確立しました。このプロセスを完了する方法を以下に示す必要があります。最も簡単な方法は、メソッド名をパラメータとして渡すことです。たとえば、前のスレッドの例では、新しいスレッドが開始され、スレッドの実行が開始される EntryPoint() というメソッドがあると仮定します。
void EntryPoint()
{
// 新しいスレッドが行う必要があることはすべて実行します
}
次のコードを使用して、新しいスレッドの実行を開始することもできます。
スレッド NewThread = 新しい Thread();
Thread.Start(EntryPoint); //間違っています
実際、これは非常に単純な方法であり、C や C++ などの一部の言語で使用されている方法です (C および C++ では、パラメーター EntryPoint は関数ポインターです)。
ただし、この直接的なアプローチでは、タイプ セーフティなどのいくつかの問題が発生する可能性があります。オブジェクト指向プログラミングを行う場合、メソッドは通常、呼び出される前にクラス インスタンスに関連付けられる必要があります。そして、この方法ではこの問題は考慮されていません。したがって、.NET Framework では構文的にこの直接的なアプローチは許可されていません。メソッドを渡す場合は、メソッドの詳細を新しいタイプのオブジェクトであるデリゲートにカプセル化する必要があります。デリゲートは特殊なタイプのオブジェクトにすぎません。特別なのは、以前に定義したすべてのオブジェクトにデータが含まれているのに対し、デリゲートにはメソッドの詳細のみが含まれていることです。
-