次のスニペットを取ります。
List<int> distances = new List<int>();
言語設計者は冗長性を意図していましたか?もしそうなら、なぜですか?
次のスニペットを取ります。
List<int> distances = new List<int>();
言語設計者は冗長性を意図していましたか?もしそうなら、なぜですか?
コードが冗長に見える理由は、初心者のプログラマーには同じものを 2 回定義しているように見えるからです。しかし、これはコードが行っていることではありません。たまたま同じタイプの 2 つの別々のものを定義しています。以下を定義しています。
List<int>
。List<int>
。次の点を考慮してください。
Person[] coworkers = new Employee[20];
ここでは、変数と割り当てられたオブジェクトが 2 つの異なる型であるため、非冗長性が明確になります (オブジェクトの型が変数の型から派生するか、変数の型を実装する場合に有効な状況)。
これについて何が冗長ですか?
List<int> listOfInts = new List<int>():
英語に翻訳: (編集、明確にするために少しクリーンアップ)
それが何をするかを考えると、それほど冗長ではありません。
もちろん、代替手段があります:
var listOfInts = new List<int>();
ここでは、C# の型推論を使用しています。これは、すぐに代入しているためです。C# は、ヒープに作成されたばかりのオブジェクトによって作成する型を判断できます。
CLR が型を処理する方法を完全に理解するには、CLR Via C#を読むことをお勧めします。
あなたはいつも言うことができます:
var distances = new List<int>();
他の人が言っているように:var
冗長性を取り除きますが、メンテナンスに悪影響を与える可能性があります。また、メンテナンスにプラスの影響を与える可能性もあると思います。
幸いなことに、Eric Lippertは、私よりもはるかに雄弁にそれについて書いています: http://csharpindepth.com/ViewNote.aspx?NoteID =63 http://csharpindepth.com/ViewNote.aspx?NoteID=61
型の宣言は、必ずしも初期化とは関係がないためです。
宣言できる
List<int> foo;
後で初期化するためにそのままにしておきます。では、冗長性はどこにありますか?たぶん、BuildList() のような別の関数から値を受け取ります。
他の人が言及しているように、新しい var キーワードを使用するとそれを回避できますが、宣言時に変数を初期化して、コンパイラがその型を認識できるようにする必要があります。
冗長であると考えるのではなく、その構造を行を節約できる機能と考えてください。
持つ代わりに
距離を一覧表示します。距離 = 新しいリスト();
c# では、それらを 1 行にまとめることができます。
1 行には、「 Distances という変数を使用し、それは List 型になります」と書かれています。別の行には、「新しいリストを割り当てて、パラメーターなしのコンストラクターを呼び出す」と書かれています。
それはあまりにも冗長ですか?多分。このようにすると、いくつかのことが得られますが、
1 . 変数宣言をオブジェクト割り当てから分離します。許可:
IEnumerable<int> distances = new List<int>();
// or more likely...
IEnumerable<int> distances = GetList();
2.コンパイラによるより強力な静的型チェックが可能になり、実行時エラーではなく、宣言が代入と一致しない場合にコンパイラ エラーが発生します。
これらは両方ともソフトウェアの作成に必要ですか? いいえ。これを行わない、および/または他の多くの点で異なる言語がたくさんあります。
「ドクター!これをすると痛い!」・「もうしないで」
C# が提供するものを必要としない、または望んでいないことがわかった場合は、他の言語を試してください。それらを使用しない場合でも、他の方法を知っていると、問題へのアプローチ方法が大幅に向上します。もしあなたが1つを使うなら、素晴らしいです!
いずれにせよ、C# を冗長すぎると非難するのではなく、「C# コンパイラによって強制される厳密な静的型チェックは必要ありません。Python を使用します」と自分に言い聞かせるのに十分な視点を見つけることができます。
次のこともできます。
var distances = new List<int>();
動的型付け言語と比較する場合にのみ「冗長」です。これは、ポリモーフィズムとコンパイル時のバグの発見に役立ちます。また、IDE のコードのオートコンプリート/インテリセンスが容易になります (使用している場合)。
C# 3.0 (.Net 3.5 に対応) のコンパイラの改善により、このような問題がいくつか解消されています。したがって、コードは次のように記述できます。
var distances = new List<int>();
更新されたコンパイラは、ステートメント内の追加情報に基づいて型を判断する能力が大幅に向上しています。つまり、代入またはジェネリックの一部としてタイプを指定する必要があるインスタンスが少なくなります。
そうは言っても、まだ改善できる領域がいくつかあります。その中には API によるものもあれば、厳密な型指定の制限によるものもあります。
冗長性自体は意図したものではありませんでしたが、すべての変数とフィールドに型宣言が必要であるという事実の副作用でした。すべてのオブジェクトのインスタンス化でも新しい式で型の名前が言及されていることを考慮すると、冗長に見えるステートメントが得られます。
varキーワードを使用した型推論により、その冗長性を排除できます。コンパイラはそれを理解するのに十分賢いです。次の C++ にも、同じことを行うautoキーワードがあります。
ただし、彼らがvarを導入した主な理由は、名前のない匿名型のためでした。
var x = new {Foo = Bar, Number = 1};
機能サポートが追加された後、C#の冗長性は確実に低下しています。
静的型付け/C構文の歴史的なアーティファクト。Rubyの例を比較してください。
distances = []
読み手に型が明らかな場合は、var を使用します。
//Use var here
var names = new List<string>();
//but not here
List<string> names = GetNames();
microsofts C# プログラミング ガイドから
var キーワードは、変数の特定の型がキーボードで入力するのが面倒な場合、または明白である場合、またはコードの可読性を向上させない場合にも役立ちます。
あなたの特定の例は確かに少し冗長ですが、ほとんどの点で C# はかなり無駄がありません。
私はこれをはるかに好むでしょう(C#)
int i;
これに(VB.NET)
Dim i as Integer
さて、あなたが選んだ特定の例は、一般的な .NET に関するもので、少し長いですが、それは C# のせいではないと思います。おそらく、「なぜ .NET コードはそんなに冗長なのか?」という質問を言い換える必要があります。
そのような怠惰のために var を使用することには、もう 1 つの問題があります。
var names = new List<string>();
var を使用する場合、「names」という名前の変数は次のように型指定されList<string>,
ますが、最終的には、によって継承されたインターフェイスの 1 つだけを使用することになります。List<T>.
IList<string> = new List<string>();
ICollection<string> = new List<string>();
IEnumerable<string> = new List<string>();
そのすべてを自動的に使用できますが、コードを書いた時点で使用したかったインターフェースを検討できますか?
この例では、var キーワードは読みやすさを改善しません。
この質問に対する回答の多くで、著者は編集者または弁明者のように考えています。優れたプログラミングの重要なルールは、同じことを繰り返さないことです。
この不要な繰り返しを避けることは、Go の明示的な設計目標です。たとえば、次のようになります。
吃音 ( ) は、 declare-and-initialize コンストラクト
foo.Foo* myFoo = new(foo.Foo)
を使用した単純な型派生によって削減されます。:=
コンパイラとコンパイラエラーに夢中になっているからです。