2012-09-20 9 views
6

私はLINQPadのいくつかのC#ステートメントを使って、どの中間言語コードが生成されているかを理解しています。C#の動的型は、ILで反映されたConsole.WriteLineを解決します

私が最初に次のコードを試してみました:

var Container = new {Name = "James"}; 
Console.WriteLine(Container.Name); 

を放出されたILの次の6つの行を見た:

IL_0001: ldstr  "James" 
IL_0006: newobj  <>f__AnonymousType0<System.String>..ctor 
IL_000B: stloc.0  
IL_000C: ldloc.0  
IL_000D: callvirt <>f__AnonymousType0<System.String>.get_Name 
IL_0012: call  System.Console.WriteLine 

私は何を期待広くなり、かなり素敵なデモンストレーションで、どのように匿名型が読み取り専用か不変か、set_Nameプロパティがないので見てください。

次私が試した文:

dynamic Container = new System.Dynamic.ExpandoObject(); 
Container.Name = "James"; 
Console.WriteLine(Container.Name); 

ILの膨大な量が放出されます。ここには貼り付けませんが、this pastebinで見つけることができます。

ダイナミックタイプとExpandoObjectの管理に関してかなりのオーバヘッドがあることを理解していますが、System.Console.WriteLineの呼び出しが内部リフレクションによって実行されたように見える理由がわかりません。コードの最初のセグメントで

IL_0072: ldstr  "WriteLine" 
.... 
IL_00BF: ldtoken  System.Console 

プロパティが取得され、格納された後、それはSystem.Console.WriteLineを呼び出し一行IL文でした。

dynamicタイプの通話では、なぜこのすべてが余分に必要ですか?

答えて

7

変数がdynamicであるため、コンパイル時にWriteLineのどのオーバーロードを呼び出すべきかを知る方法がありません。実行時まではdynamicオブジェクトの実際の型を知ることはできません。 dynamicの動作のため、コンパイル時にobjectとして扱われるだけでなく、電源の一部は、実行時に正しいオーバーロードを決定していることです。その後、

あなたが(バックExpandoObjectからToStringかだけを呼び出した後すなわちstring)ダイナミック以外の何かにオブジェクトをキャストした場合とWriteLineに渡し、あなたはコンパイル時に、その反射コールが離れて行くと、それは静的に決定表示されるはずです適切な過負荷はWriteLineです。

+0

実際、 'ToString()'トリックは( 'string'に明示的なキャストを追加しない限り)動作しません。 – svick

+0

@svickあなたは正しいです、それに応じて更新されます。 – Servy

1

何が起こっているかは、コンパイラが「遅延バインド」できるような方法でコードを作成していることです。 Lateバインディングとは、従来のデータ型やオブジェクトと同様に、コンパイル時にオブジェクトを解決するのではなく、実行時にオブジェクトが解決されている間に、アセンブリが実際にメモリに格納され実行されていることを意味します。

ReflectorまたはdotPeekでコードを見ると、動的オブジェクトが[Dynamic]属性で装飾されていることがわかります。プログラムがメモリ内で実行されている間に、この属性で装飾されたオブジェクトの場合、このオブジェクトへの呼び出しは動的Container(またはオブジェクトが呼び出されたもの)でパイプされます。このContainerは、実行時バインディングを担当するバインダーで初期化されます。それがMicrosoft.CSharp.RuntimeBinderに呼び出されたものです。このRuntimeBinderは後でプロパティやメソッドなどを呼び出すために使用されます。

これは少しクリアすることを願っています。私は自分のアンドロイドを入力しているので、説明は理想的ではないかもしれません。私は後でそれを掃除します。

+0

ローカル変数は属性を持つことができないため、この場合は属性が表示されません。 – svick

+0

@svick - いいえ、プロパティは属性を持つことができ、その例では 'Name'はプロパティです – Icemanind

+0

しかし、そのプロパティの型は' string'であり、 'DynamicAttribute'では' object'ではありません。 – svick

関連する問題