デリゲートがいるとしましょう
public delegate void StringLogging(string msg);
クラス A はこのデリゲートを使用して独自の実装を提供し、独自の実装もClass B
提供します。デリゲートの呼び出しリストには、クラス B 用とクラス BStringLogging
用の 2 つの同じメソッドが含まれていますClass A
。デリゲートは、クラス A に属する関数とクラス B に属する関数をどのように認識しますか。
内部デリゲートはとして実装されMultiCastDelegate
ます。
Delegate.GetInvocationList()
Delegate[]
mainに関連付けられた各メソッドに対応する戻り値Delegate
。
Delegate.Method
それはMethodInfo
持っていDeclaringType
ます。これDeclaringType
には、クラスがClass A
またはClass B
または他のタイプであるかどうかの情報があります。
これは、C# では慎重に隠されています。ただし、デリゲート コンストラクターは、オブジェクトとメソッド グループ参照の2 つの引数を取ります。C++/CLI 言語の方がはるかに見やすく、同じ構文糖衣はありません。たとえば、ボタンの Click イベントをサブスクライブすると、次のようになります。
this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
最初の引数、button1_Click メソッドを実装するオブジェクトのオブジェクト参照に注意してください。デリゲート型は、そのオブジェクト参照に対して特別なことは何もせず、単に格納します。基になるフィールドは Delegate.Target です。後でデリゲートが呼び出されたときに、インスタンス メソッドが必要とする非表示のthis参照も生成するために使用されます。
C# 言語では同じ構文を使用できません。コンパイラは、コンストラクターで渡したメソッド グループ参照からオブジェクト参照を推測します。これにより、事故が防止されます。このシンタックス シュガーの価格に注意してください。C# プログラマーは、イベントをサブスクライブするとターゲット オブジェクトへの参照が保持されることに気付かないことがよくあります。それが原因で診断が困難なリークが発生することは、よくある事故です。
C++/CLI の明示的な構文は、C# に完全に欠けている機能を許可し、バインドされていないデリゲートをサポートします。これは特に有用ではありませんが、C++ のメソッド ポインターの動作をモデル化しています。C++/CLI が C# シュガーを採用しなかった理由として考えられるもの。