.NETの代表者:それらはどのように構築されていますか?
-
19-09-2019 - |
質問
一般的にC#と.NETの代表者を検査している間、私はいくつかの興味深い事実に気づきました:
C#でデリゲートを作成すると、から派生したクラスが作成されます MulticastDelegate
コンストラクターで:
.method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed { }
つまり、インスタンスとメソッドへのポインターが期待されます。しかし、C#でデリゲートを構築する構文は、コンストラクターがあることを示唆しています
new MyDelegate(int () target)
私が認識できる場所 int ()
関数インスタンスとして(int *target()
C ++の関数ポインターになります)。したがって、C#コンパイラは、関数名で定義されたメソッドグループから正しい方法を選択し、デリゲートを構築します。したがって、最初の質問は、C#コンパイラ(またはVisual Studio、正確には、このコンストラクターの署名をどこから選択するのか」ということです。私は特別な属性や区別する何かに気づきませんでした。これはある種のコンパイラ/VisualStudioマジックですか?そうでない場合は、です T (args) target
C#で有効な建設?私はそれをコンパイルするために何も手に入れることができませんでした:例:
int()ターゲット= mymethod;
無効なので、何でもしています MyMetod
, 、例えば呼び出し .ToString()
その上(まあ、これはある程度理にかなっています。なぜならそれは技術的には方法だから グループ, 、しかし、私はキャストしてメソッドを明示的に選択することが可能であるべきだと思います。 (int())MyFunction
. 。それでは、この純粋にコンパイラの魔法のすべてですか?リフレクターを通して構造を見ると、さらに別の構文が明らかになります。
FUNC CS $ 1 $ 0000 = new Func(null、(intptr)foo);
これは、分解されたコンストラクターの署名と一致していますが、これはコンパイルされません!
最後の興味深いメモの1つは、クラスです Delegate
と MulticastDelegate
さらに別のコンストラクターがあります。
.Method Family HideBysig SpecialName rtspecialNameインスタンスvoid .ctor(class system.type target、string 'method')cil管理
インスタンスとメソッドポインターからタイプと文字列メソッド名への移行はどこで発生しますか?これを説明できますか runtime managed
カスタムデリゲートコンストラクターの署名のキーワード、つまりランタイムはここで仕事をしますか?
編集: :OK、だから私はこの質問によって私が言いたいことを再定式化するべきだと思います。基本的に、私はデリゲートの建設に関与するC#コンパイラ / CLRマジックだけでなく、いくつかもあることを提案しています ビジュアルスタジオ 魔法は、Intellisenseがコンストラクターの引数を提案するときにいくつかの新しい構文をひっくり返し、そのうちの1つを隠すためです(例えば、リフレクターはこの構文と制約を使用しません。
このアサーションが真であるかどうか、および関数インスタンスの構文がC#でより深い意味を持っているのか、それとも視覚的なスタジオマジックパーツによって実装された一定の形式であるかどうかを疑問に思っていました(それは無効なC#のように見えるので理にかなっています)。要するに、Intellisenseを実装していた場合、代表者のために魔法をかけるべきですか、それとも巧妙なメカニズムによって提案を構築できますか?
最終編集: :だから、人気のあるコンセンサスは、それが本当に魔法だということです。そのような行動と行動の他の例(Marc Gravellのコメントを参照)を見ると、それが事実であると確信しています。
解決
最初の引数はオブジェクト参照から解決されます(または null
静的方法の場合);そこには魔法はありません。
re 2番目 ただし、議論 - それは管理されていないポインター(ネイティブINT)です。要するに、代替手段はありません 直接 このコンストラクターを使用できるC#構文 - 特定のIL命令を使用します(ldftn
)メタデータから関数を解決します。ただし、使用できます Delegate.CreateDelegate
リフレクションを介して代表者を作成します。 ILエミットを使用することもできます(DynamicMethod
など)、しかしそれは楽しいことではありません。
他のヒント
最初にデリゲートを定義します(これは、Visual Studioがターゲットメソッドの署名をどのように知っているかです):
delegate void MyDelegate();
次に、次のような委任インスタンスを構築します。
MyDelegate method = new MyDelegate({method name});
// If this was the method you wanted to invoke:
void MethodToInvoke()
{
// do something
}
MyDelegate method = new MyDelegate(MethodToInvoke);
C#は、デリゲートの署名に一致するメソッドを自動的に選択します。
編集:Visual StudioのIntellisenseがあなたに示すとき int () target
提案では、使用できるC#メソッドの署名を示しています。 C#コンパイラは、C#表現をILに変換します。 ILはCスタイルの言語ではないため、ILの実装は異なって見えます。C#コンパイラは、実装の詳細を抽象化するために構文砂糖を提供します。
これは単なる推測ですので、私が間違っている場合は私を撃ってはいけませんが、Intellisenseはターゲットメソッドの署名を取得していると思います。 Invoke
デリゲートで定義された方法。リフレクターは、それを明確に示しています Invoke
メソッドオン System.Action<T>
は:
[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);
これは、Intellisenseが提供する署名の提案と同じです。魔法はIntellisenseです。代表団のタイプを見つけたとき、 Invoke
方法と、それに一致するターゲットをとるコンストラクターを提案します。