12

次のスニペットを取ります。

List<int> distances = new List<int>();

言語設計者は冗長性を意図していましたか?もしそうなら、なぜですか?

4

17 に答える 17

74

コードが冗長に見える理由は、初心者のプログラマーには同じものを 2 回定義しているように見えるからです。しかし、これはコードが行っていることではありません。たまたま同じタイプの 2 つの別々のものを定義しています。以下を定義しています。

  1. 型の distances という名前の変数List<int>
  2. タイプ のヒープ上のオブジェクトList<int>

次の点を考慮してください。

Person[] coworkers = new Employee[20];

ここでは、変数と割り当てられたオブジェクトが 2 つの異なる型であるため、非冗長性が明確になります (オブジェクトの型が変数の型から派生するか、変数の型を実装する場合に有効な状況)。

于 2008-09-26T03:07:56.340 に答える
15

これについて何が冗長ですか?

List<int> listOfInts = new List<int>():

英語に翻訳: (編集、明確にするために少しクリーンアップ)

  • List<int> 型のポインターを作成し、listofInts という名前を付けます。
  • listOfInts が作成されましたが、どこも指していない (null) 参照ポインターにすぎません
  • 次に、ヒープ上に List<int> 型のオブジェクトを作成し、listOfInts へのポインターを返します。
  • listOfInts はヒープ上の List<int> を指すようになりました。

それが何をするかを考えると、それほど冗長ではありません。

もちろん、代替手段があります:

var listOfInts = new List<int>();

ここでは、C# の型推論を使用しています。これは、すぐに代入しているためです。C# は、ヒープに作成されたばかりのオブジェクトによって作成する型を判断できます。

CLR が型を処理する方法を完全に理解するには、CLR Via C#を読むことをお勧めします。

于 2008-09-26T02:49:47.150 に答える
11

あなたはいつも言うことができます:

 var distances = new List<int>();
于 2008-09-26T02:44:49.173 に答える
9

他の人が言っているように:var冗長性を取り除きますが、メンテナンスに悪影響を与える可能性があります。また、メンテナンスにプラスの影響を与える可能性もあると思います。

幸いなことに、Eric Lippertは、私よりもはるかに雄弁にそれについて書いています: http://csharpindepth.com/ViewNote.aspx?NoteID =63 http://csharpindepth.com/ViewNote.aspx?NoteID=61

于 2008-09-26T12:19:49.297 に答える
4

型の宣言は、必ずしも初期化とは関係がないためです。

宣言できる

List<int> foo; 

後で初期化するためにそのままにしておきます。では、冗長性はどこにありますか?たぶん、BuildList() のような別の関数から値を受け取ります。

他の人が言及しているように、新しい var キーワードを使用するとそれを回避できますが宣言時に変数を初期化して、コンパイラがその型を認識できるようにする必要があります。

于 2008-09-26T03:01:10.350 に答える
4

冗長であると考えるのではなく、その構造を行を節約できる機能と考えてください。

持つ代わりに

距離を一覧表示します。距離 = 新しいリスト();

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 を使用します」と自分に言い聞かせるのに十分な視点を見つけることができます。

于 2008-09-26T03:09:36.103 に答える
3

次のこともできます。

var distances = new List<int>();
于 2009-01-07T20:25:47.687 に答える
2

動的型付け言語と比較する場合にのみ「冗長」です。これは、ポリモーフィズムとコンパイル時のバグの発見に役立ちます。また、IDE のコードのオートコンプリート/インテリセンスが容易になります (使用している場合)。

于 2009-01-08T14:22:06.003 に答える
2

C# 3.0 (.Net 3.5 に対応) のコンパイラの改善により、このような問題がいくつか解消されています。したがって、コードは次のように記述できます。

var distances = new List<int>();

更新されたコンパイラは、ステートメント内の追加情報に基づいて型を判断する能力が大幅に向上しています。つまり、代入またはジェネリックの一部としてタイプを指定する必要があるインスタンスが少なくなります。

そうは言っても、まだ改善できる領域がいくつかあります。その中には API によるものもあれば、厳密な型指定の制限によるものもあります。

于 2008-09-26T02:49:47.697 に答える
2

冗長性自体は意図したものではありませんでしたが、すべての変数とフィールドに型宣言が必要であるという事実の副作用でした。すべてのオブジェクトのインスタンス化でも新しい式で型の名前が言及されていることを考慮すると、冗長に見えるステートメントが得られます。

varキーワードを使用した型推論により、その冗長性を排除できます。コンパイラはそれを理解するのに十分賢いです。次の C++ にも、同じことを行うautoキーワードがあります。

ただし、彼らがvarを導入した主な理由は、名前のない匿名型のためでした。

var x = new {Foo = Bar, Number = 1};
于 2008-09-26T03:10:02.060 に答える
1

機能サポートが追加された後、C#の冗長性は確実に低下しています。

于 2008-09-26T02:45:42.883 に答える
1

静的型付け/C構文の歴史的なアーティファクト。Rubyの例を比較してください。

distances = []
于 2008-09-26T02:46:05.690 に答える
1

読み手に型が明らかな場合は、var を使用します。

//Use var here
var names = new List<string>();

//but not here
List<string> names = GetNames();

microsofts C# プログラミング ガイドから

var キーワードは、変数の特定の型がキーボードで入力するのが面倒な場合、または明白である場合、またはコードの可読性を向上させない場合にも役立ちます。

于 2008-09-29T01:31:40.250 に答える
0

あなたの特定の例は確かに少し冗長ですが、ほとんどの点で C# はかなり無駄がありません。

私はこれをはるかに好むでしょう(C#)

int i;

これに(VB.NET)

Dim i as Integer

さて、あなたが選んだ特定の例は、一般的な .NET に関するもので、少し長いですが、それは C# のせいではないと思います。おそらく、「なぜ .NET コードはそんなに冗長なのか?」という質問を言い換える必要があります。

于 2008-09-26T02:54:18.107 に答える
0

そのような怠惰のために 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 キーワードは読みやすさを改善しません。

于 2009-01-08T08:50:29.260 に答える
0

この質問に対する回答の多くで、著者は編集者または弁明者のように考えています。優れたプログラミングの重要なルールは、同じことを繰り返さないことです。

この不要な繰り返しを避けることは、Go の明示的な設計目標です。たとえば、次のようになります。

吃音 ( ) は、 declare-and-initialize コンストラクトfoo.Foo* myFoo = new(foo.Foo)を使用した単純な型派生によって削減されます。:=

于 2010-05-04T17:53:22.923 に答える
-1

コンパイラとコンパイラエラーに夢中になっているからです。

于 2008-09-26T02:45:32.417 に答える