web-dev-qa-db-ja.com

匿名型と動的型

C#3.0の匿名型(var)とc#4.0で登場する動的型(動的)の本当の違いは何ですか?

40
Satish

匿名型は、コンパイラによって生成された実際の型であり、ユーザーのために作成されます。これの良い点は、コンパイラがこのタイプをPOCOであるため、後でそれを必要とする他の操作に再利用できることです。

動的型についての私の理解は、それらが遅延バインドされていることです。つまり、CLR(またはDLR)は実行時にオブジェクトを評価し、ダックタイピングを使用してメンバーによるオブジェクトへのアクセスを許可または禁止します。

したがって、違いは、匿名型はコンパイラが認識できる真のPOCOであるが、使用できるのは動的型のみであり、動的型は遅延バインドされた動的オブジェクトであるということだと思います。

20
Andrew Hare

あなたは3つの完全に異なる直交するものを混ぜているようです:

  • 静的vs.動的入力
  • マニフェストと暗黙的入力
  • 名前付きvs.匿名タイプ

これらの3つの側面は完全に独立しており、互いに何の関係もありません。

静的vs.動的型付けはを指します型チェックが行われる場合:動的型付けは実行時で行われ、静的型付けは実行時前に行われます

マニフェストと暗黙的タイピングは、タイプがソースコードのマニフェストであるかどうかを示します:マニフェストタイピングは、プログラマーがタイプをに書き込む必要があることを意味しますソースコード、暗黙のタイピングは、型システムがそれ自体でそれらを理解することを意味します。

名前付きvs.匿名タイプは、タイプに名前があるかどうかを示します。

C#4.0のdynamicキーワードは、この変数、パラメーター、メソッド、フィールド、プロパティ...動的に型付けされたもの、つまりその型が実行時にチェックされることを意味します。動的として型付けされていないものはすべて静的に型付けされます。型が静的か動的かによって、型チェックがいつ行われるかが決まるだけでなく、C#4.0ではメソッドディスパッチがいつ行われるかも決まります。 C#では、メソッドのディスパッチは静的タイプに基づいて実行前に実行されますが(もちろん、ランタイムサブタイプの多態性は例外です)、C#4.0で動的に型指定されたオブジェクトでは、メソッドのディスパッチはランタイムタイプに基づいて実行時に行われます。

C#3.0のvarキーワードは、このローカル変数が暗黙的に型付けされるであることを意味します。つまり、プログラマーが型を明示的に書き留める代わりに、型システムがそれを独自に把握します。これは、少なくともC#3.0では、動的型付けとは何の関係もありません。変数は、自分で型を書き留めたかのように、強く静的に型付けされます。これは単なる便宜です。たとえば、型システムが明確にであることがわかるのに、なぜすべての型名2回HashMap<int, string> foo = new HashMap<int, string>();に書き留める必要があるのでしょうか。 fooHashMap<int, string>なので、代わりにvar foo = new HashMap<int, string();と記述します。これについて動的または匿名のものは何もないことに注意してください。タイプは静的で、名前はHashMap<int, string>です。もちろん、C#4.0では、型システムが割り当ての右側が動的であると判断した場合、左側の変数の型は動的になります。

C#3.0の匿名型は、この型に名前がないことを意味します。実際、実際の匿名型では、共通型システムに対して後方互換性のない変更が必要になるため、実際にカーテンの後ろで発生するのは、コンパイラが非常に長い、タイプの非常にランダムで一意で違法な名前であり、匿名タイプが表示される場所にその名前を入れます。しかし、プログラマーの観点からは、型には名前がありません。なぜこれが便利なのですか?まあ、時々あなたはあなたがほんの少しだけ必要としそしてそれから再び捨てる中間結果を持っています。このような一時的なタイプに独自の名前を付けると、それらを単に値しない重要性のレベルにまで高めることができます。しかし、繰り返しになりますが、これについて動的なことは何もありません。

では、型に名前がない場合、プログラマーはどのようにそれを参照できますか?まあ、彼女はできません!少なくとも直接ではありません。プログラマーcanができることは、型を記述することです。1つは型stringの「name」と呼ばれ、もう1つは型intの「id」と呼ばれる2つのプロパティがあります。それは私が望むタイプですが、それが何と呼ばれるかは気にしません。

ここからピースが集まり始めます。 C#では、型の名前を明示的に書き留めて、ローカル変数の型を宣言する必要があります。しかし、名前のない型の名前をどのように書き留めることができますか?ここでvarが登場します。C#3.0以降、これは実際には真実ではなくなったためです。名前を書き留める必要がなくなったため、コンパイラにそれを理解するように指示することもできます。したがって、上記の最初の段落で書いたことは真実ですが、暗黙の入力と匿名の型は他とは何の関係もありませんが、匿名の型は暗黙の入力なしではかなり役に立たないことも事実です。

ただし、その逆は当てはまらないことに注意してください。暗黙的な型指定は、匿名型がなくても完全に役立ちます。 var foo = HashMap<int, string>は完全に理にかなっており、匿名型は見えません。

94
Jörg W Mittag

dynamicタイプは基本的にobjectですが、すべてのメソッド/プロパティ/演算子などの呼び出しを解決します実行時 DLRまたは他のプロバイダー(リフレクションなど)を介して。

これにより、VB with Option Strict Off であり、COMまたはDLRタイプへの呼び出しに非常に用途が広くなります。

no動的なコンパイル時の型チェックがあります。逆に言えば、匿名型は適切な静的型で型チェックされた獣です(きれいではありませんが、リフレクターで見ることができます)。

さらに、匿名型はコンパイラーによって排他的に処理できます。 dynamicには広範なランタイムサポートが必要です。したがって、匿名型はC#機能ですが、dynamicは主に.NET4.0で実装されます(一部のC#4.0サポート付き)。

18
Marc Gravell

3回あり、3人の俳優がいます-毎回1人。

  • 設計時-プログラマー
  • コンパイル時-c#コンパイラ
  • ランタイム-.netランタイム

匿名型は、コンパイラーによって宣言され、名前が付けられます。この宣言は、プログラマーの仕様(彼が型をどのように使用したか)に基づいています。これらのタイプは、プログラマーがプロセスを離れた後に名前が付けられているため、プログラマーには名前がないように見え、したがって「匿名」です。

  • プログラマーは言う:いくつかのタイプには名前と住所があります
  • コンパイラは次のように述べています。名前とアドレスのプロパティとフィールド、両方の文字列を持つxyzという名前の型があります。
  • ランタイムによると:xyzとプログラマーが作成したタイプの違いはわかりません。

c#での動的型付けを使用すると、コンパイル時に存在する場合と存在しない場合があるメソッドを呼び出すことができます。これは、コンパイルされていないpythonまたはjavascriptを呼び出す場合に役立ちます。

  • プログラマーは次のように述べています。この車のインスタンスを動的型として扱います。さて、いんちき。
  • コンパイラは言う:動的型付けえ?大丈夫でなければなりません。確認できないので文句は言いません。
  • ランタイムは、car、quackのインスタンスを作成しようとします。
7
Amy B

ここでアンダーのプレゼンテーションをチェックしてください:

http://channel9.msdn.com/pdc2008/TL16/

HTM

7
Colby Africa

物事を片付けるための小さなコードのようなものはありません:

// anonymous types
var anonType = new {Id = "123123123", Name = "Goku", Age = 30, DateAdded = new DateTime()};
// notice we have a strongly typed anonymous class we can access the properties with
Console.WriteLine($"Anonymous Type: {anonType.Id} {anonType.Name} {anonType.Age} {anonType.DateAdded}");
// compile time error
//anonType = 100;

// dynamic types
dynamic dynType = 100.01m;
Console.WriteLine($"Dynamic type: {dynType}");
// it's ok to change the type however you want
dynType = new List<DateTime>();
Console.WriteLine($"Dynamic type: {dynType}");

// mix dynamic and anonymous
dynamic dynamicAnonymousType = new {Id = 8000, FirstName = "Goku", Gender = "male", IsSuperSaiyan = true};
// Wasn't sure this would work but it does! However, you lose intellisense on the FirstName so you have to type it manually.
Console.WriteLine($"FirstName: {dynamicAnonymousType.FirstName}");
dynamicAnonymousType = 100;
Console.WriteLine(dynamicAnonymousType);
// runtime error
Console.WriteLine($"Id: {dynamicAnonymousType.FirstName}");
2
goku_da_master