C#3.0の匿名型(var)とc#4.0で登場する動的型(動的)の本当の違いは何ですか?
匿名型は、コンパイラによって生成された実際の型であり、ユーザーのために作成されます。これの良い点は、コンパイラがこのタイプをPOCOであるため、後でそれを必要とする他の操作に再利用できることです。
動的型についての私の理解は、それらが遅延バインドされていることです。つまり、CLR(またはDLR)は実行時にオブジェクトを評価し、ダックタイピングを使用してメンバーによるオブジェクトへのアクセスを許可または禁止します。
したがって、違いは、匿名型はコンパイラが認識できる真のPOCOであるが、使用できるのは動的型のみであり、動的型は遅延バインドされた動的オブジェクトであるということだと思います。
あなたは3つの完全に異なる直交するものを混ぜているようです:
これらの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>();
に書き留める必要があるのでしょうか。 foo
はHashMap<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>
は完全に理にかなっており、匿名型は見えません。
dynamic
タイプは基本的にobject
ですが、すべてのメソッド/プロパティ/演算子などの呼び出しを解決します実行時 DLRまたは他のプロバイダー(リフレクションなど)を介して。
これにより、VB with Option Strict Off
であり、COMまたはDLRタイプへの呼び出しに非常に用途が広くなります。
no動的なコンパイル時の型チェックがあります。逆に言えば、匿名型は適切な静的型で型チェックされた獣です(きれいではありませんが、リフレクターで見ることができます)。
さらに、匿名型はコンパイラーによって排他的に処理できます。 dynamic
には広範なランタイムサポートが必要です。したがって、匿名型はC#機能ですが、dynamic
は主に.NET4.0で実装されます(一部のC#4.0サポート付き)。
3回あり、3人の俳優がいます-毎回1人。
匿名型は、コンパイラーによって宣言され、名前が付けられます。この宣言は、プログラマーの仕様(彼が型をどのように使用したか)に基づいています。これらのタイプは、プログラマーがプロセスを離れた後に名前が付けられているため、プログラマーには名前がないように見え、したがって「匿名」です。
c#での動的型付けを使用すると、コンパイル時に存在する場合と存在しない場合があるメソッドを呼び出すことができます。これは、コンパイルされていないpythonまたはjavascriptを呼び出す場合に役立ちます。
物事を片付けるための小さなコードのようなものはありません:
// 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}");