いつ使うべきか疑問に思っていましたvar
か?
おそらくプリミティブとさらにいくつかの奇妙なケースを除いて、C# のほとんどすべてが Object から派生します。
では、その実際の型を使用する方が良いのではないでしょうか? または少なくともobject
?
(私はしばらくの間プログラミングをしてきましたが、私の厳密な見方はそれvar
は悪です)
あなたは誤解しています:var
タイプではありません。初期化に基づいて、変数に正しいvar
型を使用するようコンパイラに指示します。
例:
var s = "hello"; // s is of type string
var i = 42; // i is of type int
var x = new [] { 43.3 }; // x is of type double[]
var y = new Foo(); // y is of type Foo
を使用する場合、変数は引き続き強く型付けされvar
ます。
結果として、var
「悪」ではありません。それどころか、非常に便利で、他の場所で述べたように、私はそれを広く使用しています. C# の背後にいる主要な人物の 1 人である Eric Lippert も、悪い習慣であるかどうかについて非常に詳細に書いています。var
一言で言えば「ない」。
あなたは と混同var
しているdynamic
と思います。使用var
は、型名全体を書き出した場合とまったく同じ*であり、コンパイラはそれらを同じコードにレンダリングします。var
Eric Lippert のブログでは、キーワードの機能と使用時期に関する優れた情報が提供されています。
Eric Lippert の記事Uses and misuses of Implicittyping から:
要約すると、私のアドバイスは次のとおりです。
- 必要な場合は var を使用してください。匿名型を使用している場合。
- 宣言の型がイニシャライザから明らかな場合、特にオブジェクトの作成の場合は、var を使用します。これにより、冗長性が排除されます。
- コードが変数のセマンティックな「ビジネス目的」を強調し、そのストレージの「機械的」詳細を軽視する場合は、var の使用を検討してください。
- コードを正しく理解して維持するために必要な場合は、明示的な型を使用します。
- 「var」を使用するかどうかに関係なく、わかりやすい変数名を使用してください。変数名は、ストレージの詳細ではなく、変数のセマンティクスを表す必要があります。「decimalRate」は悪いです。「利率」いいですね。
※「まったく同じ」という私の発言に異議を唱える人もいるかもしれません。厳密には匿名型には当てはまりませんが、それは型名を合法的に書き出すことができないためです。
使用object
すると、すべての静的型情報が失われます(値型で使用すると、ボクシングも発生します)。したがって、を使用することは、を使用することobject
とは大きく異なりvar
ます。
var
一方、actual(static)タイプを使用するのと同じです。したがって、実際のタイプが不可能または不便であると述べるときに使用します。
必要なシナリオの1つvar
は、匿名タイプを使用する場合です。それらには名前がないため(nitpick:コンパイラによって生成された、不明な名前のみ)、型に明示的に名前を付けることはできません。
使用が便利な場合の1つvar
は、typenameが非常に長い場合です。これは、ネストされたジェネリックを使用している場合に発生することがあります。
また、foreach
ループでは、安全でない暗黙のキャストを回避します。
var
とobject
はまったく異なる2つのものです。
を使用var
すると、コンパイラがタイプを推測します。Anobject
はオブジェクトであり、C#は強く型付けされた言語であるため、インスタンスに関する情報はすべて失われます。
C#仕様のセクション26.1を参照してください。
暗黙的に型指定されたローカル変数宣言では、宣言されているローカル変数の型は、変数の初期化に使用される式から推測されます。ローカル変数宣言がvarを型として指定し、varという名前の型がスコープ内にない場合、宣言は暗黙的に型指定されたローカル変数宣言です。
あなたの「厳密な視点」は少し誤解されています...var
実際のタイプを使用します。コンパイラーは、右側の式の戻り型を分析し、それを割り当ての型として使用します。
var
タイプではありません。var
コンパイラに「ここに適切な型名を入力するのがわからない/わざわざできないので、このステートメントのコンテキストに基づいて型を推測してください」と言います。
Object
オブジェクトをタイプにキャストしますObject
。その結果、型情報が失われるため、階層の下位レベルで定義されている特定のメソッドを呼び出したり、プロパティにアクセスしたりすることはできなくなりますObject
。