ビルはどのような区別をしていますか?
ビルが行っている違いは、多くの人が次のように考えていることです。
var x = Whatever();
x.Foo();
Whateverによって実行時に返されるオブジェクトのタイプに基づいて、実行時にどのメソッドFooを呼び出すかが決まります。それは真実ではない; それは
dynamic x = Whatever();
x.Foo();
var
単に「実行時に計算する」ではなく、「コンパイル時に型を計算して代入する」という意味です。
だから私が持っているなら
dynamic i = 5;
Console.WriteLine(i);
何が起こるのですか?
コンパイラは、道徳的に次のようなコードを生成します。
object i = (object)5;
DynamicCallSite callSite = new DynamicCallSite(typeof(Console), "WriteLine"));
callSite.Invoke(i);
それよりも少し複雑です。一つには、コールサイトはキャッシュされます。しかし、これはあなたにそれの味を与えます。
呼び出しメソッドはi
、経由でその型を要求してからGetType
、リフレクションオブジェクトを理解できるC#コンパイラの特別なバージョンを起動します。Console
これは、 namedのメンバーに対してオーバーロード解決を行い、最初にintとして入力された場合に呼び出されたであろうWriteLine
オーバーロードを判別します。Console.WriteLine
i
次に、その呼び出しを表す式ツリーを生成し、式ツリーをデリゲートにコンパイルし、それを呼び出しサイトにキャッシュして、デリゲートを呼び出します。
2回目にこれを行うと、キャッシュされた呼び出しサイトはそのキャッシュを調べ、最後i
にintであったときに、特定のデリゲートが呼び出されたことを確認します。したがって、2回目は、呼び出しサイトの作成と過負荷解決の実行をスキップし、デリゲートを呼び出すだけです。
詳細については、以下を参照してください。
http://ericlippert.com/2012/10/22/a-method-group-of-one/
http://ericlippert.com/2012/11/05/dynamic-contagion-part-one/
http://ericlippert.com/2012/11/09/dynamic-contagion-part-two/
この機能の歴史的な視点は、ChrisとSamのブログから入手できます。
http://blogs.msdn.com/b/cburrows/archive/tags/dynamic/
http://blogs.msdn.com/b/samng/archive/tags/dynamic/
彼らは多くの実装を行いました。ただし、これらの記事の一部は、古い設計の選択を反映しています。残念ながら、「ファントムメソッド」アルゴリズムを使用したことはありません。(優れたアルゴリズムではありませんが、優れた名前です!)