14

私は最近、IList ではなく厳密に型指定された配列を返すことを好む理由を誰かに尋ねていました。私はずっと、インターフェイスに対するプログラミングが、プロジェクトの存続期間が長い場合に最も柔軟で最善の方法であると考えていました。それで、彼がこう答えたとき、私は奇妙に感じました。

私たちは通常、可変型よりも不変型を好みます。配列は不変です。IList ではありません。

私はこの声明を理解しているかどうか完全には確信が持てません。誰でもこれを明確にするのを助けることができますか?

皆さんが提供できる助けをありがとう。

4

11 に答える 11

13

「彼」が誰であれ、このトピックに関しては 100% 間違っています。配列は非常に可変です。実際、これは配列を返さない理由の 1 つです。呼び出し元が配列の要素を好きなように変更するのを防ぐ方法はありません。

配列が不変である唯一の方法は、その長さです。配列が割り当てられると、その長さは変更できません。Array.Resize などの API でさえ、実際には配列のサイズを変更しません。新しい配列を割り当て、内容をコピーして、新しい配列を返します (この場合は参照による)。

ただし、不変データを返す方が良い場合が多いことに同意します。主なものは、完全なコピーを行わずにクラスの内部コレクションへの参照を返すことができると同時に、呼び出し元が内部状態をいじるのを防ぐことができることです。ほとんどの可変コレクションは、そのような保証を行うことができません。

于 2009-05-02T23:47:02.233 に答える
11

配列の長さプロパティは不変であるため、彼はおそらく配列がIListよりも不変であるか、間違った単語を使用してコンクリートを不変と交換したのではないかと考えたと思います。誰が知っていますが、それは奇妙な答えです。

リストを返すことで、それを変更しても問題がないこと、または配列を返すときに変更される可能性があることを少し暗示していると思いますが、それほど意味はありません。

たとえば、リポジトリの上にオブジェクトモデルがあり、リストを返すGetCars()のようなメソッドがあり、ジュニアプログラマーが車を見た場合、Add(Car c)...彼は考えるのに完全に狂っていたと思いますかcars.Add(new Car())は、実際に車をリポジトリに追加する可能性がありますか?配列は本質的により明示的です。

Page.Controls.Addなどのプロパティでは、リストの使用がより適切だと思います

いくつかの理由から、Listよりも頻繁に配列を返す方が好きです。

  • 癖。1.0/1.1のコレクションSUCKED

  • 私のメソッドは、可能な限り最も単純で最も軽量なオブジェクトを返すことを好みます。配列をリストにする必要がある場合、それは簡単です。

  • これらは.net1.1で使用でき、古いバージョンのランタイムをサポートする必要が生じた場合にリファクタリングの表面を減らします。コードの少なくとも一部を再利用するか、同じオブジェクトモデルを適用できます。

于 2009-05-03T11:33:19.803 に答える
10

私はいつもReadOnlyCollectionを好みます。リストのすべての利点、ただし読み取り専用。

于 2009-05-03T11:39:09.727 に答える
7

原則として彼は正しいですが、彼はそれを適切に実践する方法を知りません...

通常、可変タイプよりも不変タイプを優先します。

それは正しいです。不変型は操作しやすいです

配列は不変です。IListはそうではありません。

それは正しくありません。どちらも不変ではありません。

不変のコレクションを返す場合は、(メソッドを使用して)IEnumerable<T>またはを返します。それでも、オブジェクト自体が不変でない場合、それらはオブジェクトを保護しません。コレクションからのみ読み取ることができますが、許可されている場合は、各オブジェクトのデータを変更できます。ReadOnlyCollection<T>List<T>.AsReadOnly

また、返却するコレクションの「所有権」を考慮する必要があります。配列を返すことだけを目的として配列を作成している場合は、配列を完全に制御しない理由はありません。一方、クラスのメンバーであるコレクションを返す場合は、必要なだけアクセスを許可する必要があります。

于 2009-05-03T00:21:05.210 に答える
7

彼が言いたかったことの 1 つは、IList には Insert、Remove、および Add メソッドが含まれているため、コレクション自体を変更できるということです。一方、T[] には要素を追加できません。

FxCop は、代わりに ReadOnlyCollection を返すことを推奨していることを付け加えておきます。インデクサーは読み取り専用であるため、要素を変更することはできず、Add などのメソッドはすべて NotSupportedException をスローします。

于 2009-05-02T23:44:37.217 に答える
2

私にもわかりません。配列は、そのサイズを除いて、非常に変更可能です。個々の要素は引き続き変更できます。おそらく彼は、配列が値型であり、リストが参照型であることを意味していたのでしょう。知らない。

いずれにせよ、この件に関するEric Lippert の意見をご覧になることをお勧めします。議論のための弾薬も提供できます。

于 2009-05-02T23:38:51.643 に答える
1

おそらく、この人は彼が何について話しているのか分からないのですか?

于 2009-05-02T23:36:26.360 に答える
1

Interface を実際の型自体よりも戻り型として使用する理由は、呼び出し元から内部実装を隠すためです。これにより、実装は、アプリケーションの残りの部分に再帰することなく、実際の型を変更できます。

可変または不変以外の理由で、内部で使用されるコレクションを外部で使用するために配列にコピーすることは意味がありません。

別の問題は次のとおりです。 - 厳密に型指定されたデータのリストを返すかどうか。IList または IList。厳密に型指定されたデータの使用は常に優先されます。- 可変または不変。ICollection、IList または IEnumerator データに許可したいものを返します。読み取り専用リストの場合、IEnumerator のみを返します。呼び出し元がコレクションの変更を許可されている場合は、ICollection または IList を使用します。

于 2009-05-03T02:45:42.677 に答える
0

基本的に彼は、「実行時に簡単に変更できない構造を好みます。エラーの影響を受けにくいと考えているからです」と言っています。この場合、それが正しいかどうかは別の問題です。

于 2009-05-02T23:36:35.143 に答える
0

おそらく彼は、配列のサイズが「不変」であることを意味していたのでしょうか? 基本的に、サイズを 1 回宣言すると、それに固執します。リストでは、いつでも「追加」を使用できます。

リストのサイズが確か場合は、配列の方が少し速いのではないでしょうか?

于 2009-05-02T23:45:17.120 に答える
0

良い。IList は、既に存在する項目を変更するだけでなく、項目を追加および削除できるという意味で変更可能です。配列を使用すると、個々の項目をいじることができますが、特定のインデックスが完全に無効になることはありません。不変性を好む理由はいくつもあります。たとえば、偶発的なデータ破損の可能性がはるかに小さくなります。

于 2009-05-02T23:46:08.723 に答える