c# 3.0 の匿名型 (var) と c# 4.0 で登場する動的型 (dynamic) の実際の違いは何ですか?
5 に答える
あなたは3つの完全に異なる直交するものを混ぜているようです:
- 静的型付けと動的型付け
- マニフェストと暗黙のタイピング
- 名前付きタイプと匿名タイプ
これらの3つの側面は完全に独立しており、互いに何の関係もありません。
静的型付けと動的型付けは、型チェックが行われるタイミングを指します。動的型付けは実行時に行われ、静的型付けは実行前に行われます。
マニフェストと暗黙の型付けは、型がソースコードに明示されているかどうかを示します。マニフェスト型付けとは、プログラマーが型をソースコードに書き込む必要があることを意味し、暗黙的な型付けとは、型システムがそれを独自に把握することを意味します。
名前付きタイプと匿名タイプは、タイプに名前があるかどうかを示します。
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の匿名型は、この型に名前がないことを意味します。実際、実際の匿名型では、共通型システムに対して後方互換性のない変更が必要でした。そのため、実際にカーテンの後ろで行われるのは、コンパイラが型に対して非常に長く、非常にランダムで、一意で不正な名前を生成し、匿名型が表示される場所でのその名前。しかし、プログラマーの観点からは、型には名前がありません。なぜこれが便利なのですか?まあ、時々あなたはあなたがほんの少しだけ必要としそしてそれから再び捨てる中間結果を持っています。このような一時的なタイプに独自の名前を付けると、それらを単純に値しない重要性のレベルにまで高めることができます。しかし、繰り返しになりますが、これについて動的なことは何もありません。
では、型に名前がない場合、プログラマーはどのようにそれを参照できますか?まあ、彼女はできません!少なくとも直接ではありません。プログラマーができることstring
は、タイプを記述することです。1つはタイプの「name」と呼ばれ、もう1つはタイプの「id」と呼ばれる2つのプロパティがありint
ます。それは私が望むタイプですが、それが何と呼ばれるかは気にしません。
ここからピースが集まり始めます。C#では、型の名前を明示的に書き留めて、ローカル変数の型を宣言する必要があります。しかし、名前のない型の名前をどのように書き留めることができますか?これがvar
出番です。C#3.0以降、これは実際には真実ではなくなったためです。名前を書き留める必要がなくなったため、コンパイラにそれを理解するように指示することもできます。したがって、上記の最初の段落で書いたことは真実ですが、暗黙の型付けと匿名型は他とは何の関係もありませんが、匿名型は暗黙の型付けなしではかなり役に立たないことも事実です。
ただし、その逆は当てはまらないことに注意してください。暗黙的な型指定は、匿名型がなくても完全に役立ちます。var foo = HashMap<int, string>
完全に理にかなっており、匿名のタイプは見えません。
匿名型は、コンパイラによって生成された実際の型であり、ユーザーのために作成されます。これの良いところは、POCO であるため、コンパイラが後でこの型を必要とする他の操作に再利用できることです。
つまり、CLR (または DLR) は実行時にオブジェクトを評価し、ダック タイピングを使用してオブジェクトへのメンバー アクセスを許可または禁止します。
したがって、違いは、匿名型はコンパイラが見ることができる真の POCO ですが、使用できるのは動的型だけであり、動的型は遅延バインドされた動的オブジェクトであるということだと思います。
dynamic
型は基本的に ですが、DLR またはその他のプロバイダー (リフレクションなど) を介して実行時にobject
すべてのメソッド / プロパティ / オペレーターなどの呼び出しを解決します。
これにより、VB with によく似たものOption Strict Off
になり、COM や DLR 型への呼び出しに非常に汎用性が高くなります。
dynamic を使用すると、コンパイル時に型チェックが行われません。要するに、匿名型は静的型付けされ、型チェックされた適切な獣です (見栄えはよくありませんが、リフレクターで見ることができます)。
さらに、匿名型はコンパイラによって排他的に処理されます。dynamic
広範なランタイム サポートが必要です。そのため、匿名型は C# の機能ですが、dynamic
大部分は .NET 4.0 で実装されます (一部の C# 4.0 をサポートしています)。
3 回あり、各回に 1 人ずつ、3 人の俳優が出演します。
- 設計時 - プログラマー
- コンパイル時 - c# コンパイラ
- ランタイム - .net ランタイム
匿名型は、コンパイラによって宣言され、名前が付けられます。この宣言は、プログラマーの仕様 (型の使用方法) に基づいています。これらの型は、プログラマーがプロセスを離れた後に名前が付けられるため、プログラマーには名前がないように見え、したがって「匿名」です。
- プログラマーは次のように述べています: 一部の型には名前とアドレスがあります
- コンパイラは次のように述べています: 名前とアドレスのプロパティとフィールドを持つ xyz という名前の型があり、どちらも文字列です。
- ランタイムは次のように述べています: xyz とプログラマーが作成した型との違いはわかりません。
C# の動的型付けにより、コンパイル時に存在する場合も存在しない場合もあるメソッドを呼び出すことができます。これは、コンパイルされていない python または javascript を呼び出す場合に便利です。
- プログラマーは次のように言います: 車のこのインスタンスを動的な型として扱います。さあ、クワッ。
- コンパイラは次のように述べています: 動的型付けですか? 大丈夫でなければなりません。確認できないので文句は言いません。
- ランタイムは car のインスタンスを作成しようとします。
物事を片付けるための小さなコードのようなものはありません:
// 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}");