MyClass[] array;
List<MyClass> list;
一方が他方より望ましい場合のシナリオは何ですか?なぜ?
MyClass[] array;
List<MyClass> list;
一方が他方より望ましい場合のシナリオは何ですか?なぜ?
回答:
実際には、配列を使用することはまれです。List<T>
配列のサイズ変更にはコストがかかるため、データを追加または削除したいときは必ず使用してください。データが固定長であることがわかっていて、非常に特定の理由(ベンチマーク後)でマイクロ最適化を行う場合は、配列が役立ちます。
List<T>
LINQは配列よりもはるかに多くの機能を提供します(ただし、LINQはそれを少し均一化します)。ほとんどの場合、正しい選択です。params
もちろん、引数を除いて。;-p
カウンターとして- List<T>
一次元です。ここで、として次のような矩形(ETC)のアレイを有する有しint[,]
又はstring[,,]
-が、オブジェクトモデルで(必要な場合)、そのようなデータをモデル化する他の方法があります。
以下も参照してください。
それは私が作る、と多くの私の中のアレイの使用のいるProtobufネットプロジェクト。完全にパフォーマンスのために:
byte[]
はエンコーディングにかなり不可欠です。byte[]
基礎となるストリーム(およびvv)に送信する前に満たすローカルローリングバッファーを使用します。他よりも速いBufferedStream
;Foo[]
ではなくオブジェクトの配列ベースのモデルを使用しますList<Foo>
。しかし、これは間違いなく例外です。一般的な基幹業務の処理では、List<T>
毎回勝利します。
私が驚いたリンクを追加するために答えるだけでは、まだ言及されていません。EricのLippertの「配列はやや有害だと考えられている」というブログエントリ。
タイトルから、実用的な場所であればコレクションを使用するように提案していると判断できますが、Marcが正しく指摘しているように、配列が本当に唯一の実用的な解決策である場所はたくさんあります。
推奨する他の回答にもかかわらず、List<T>
処理時には配列を使用する必要があります。
List<T>
バイト配列ではなくhere を使用することに反対することは何ですか?
本当にパフォーマンスに関心がない限り、つまり「C ++ではなく.Netを使用しているのはなぜですか?」List <>を使用する必要があります。保守が簡単で、バックグラウンドで配列のサイズを変更するというすべての汚い作業を行います。(必要に応じて、List <>は配列サイズの選択に関して非常に優れているため、通常は必要ありません。)
コレクション自体の不変性がクライアントとプロバイダーのコード間のコントラクトの一部である場合(必ずしもコレクション内のアイテムの不変性ではない)、およびIEnumerableが適切でない場合は、Listを優先して配列を使用する必要があります。
例えば、
var str = "This is a string";
var strChars = str.ToCharArray(); // returns array
「strChars」を変更しても、「str」の基礎となる型に関する実装レベルの知識に関係なく、元の「str」オブジェクトは変更されないことは明らかです。
しかし、
var str = "This is a string";
var strChars = str.ToCharList(); // returns List<char>
strChars.Insert(0, 'X');
この場合、挿入メソッドが元の「str」オブジェクトを変更するかどうかは、そのコードスニペットだけでは明確ではありません。その決定を行うには、Stringの実装レベルの知識が必要であり、これはDesign by Contractアプローチを破ります。文字列の場合、それは大した問題ではありませんが、他のほとんどすべての場合に大問題になる可能性があります。リストを読み取り専用に設定すると効果がありますが、コンパイル時ではなく実行時エラーが発生します。
To
、元のインスタンスを変更できないオブジェクトが作成されますが、strChars as char[]
有効な場合は、元のオブジェクトを変更できるようになります。
str
、内部配列を使用し、ToCharArray
この配列への参照を返すクライアントは変異することができるstr
大きさが残って固定しても、その配列の要素を変更することによって。しかし、「strChars」を変更しても元の「str」オブジェクトが変更されないことは明らかです。ここで何が欠けていますか?私が見ることができることから、どちらの場合でも、クライアントは内部表現にアクセスでき、タイプに関係なく、これは何らかの種類の変更を許可します。
ほとんどの場合、a List
を使用するだけで十分です。List
用途内部の配列は、そのデータを処理し、より多くの要素を追加するときに自動的に配列のサイズを変更するにはList
、それがより簡単にあなたが事前に容量を知っている必要があり、配列、より使用できるようになり、その電流容量、より。
C#のリストまたは単に逆コンパイルの詳細については、http: //msdn.microsoft.com/en-us/library/ms379570(v=vs.80).aspx# datastructures20_1_topic5を参照してくださいSystem.Collections.Generic.List<T>
。
多次元データが必要な場合(たとえば、マトリックスを使用したり、グラフィックスプログラミングで)、おそらくarray
代わりに使用します。
いつものように、メモリやパフォーマンスに問題がある場合は、それを測定してください!そうでなければ、コードについて誤った仮定をする可能性があります。
配列対 リストは、保守性とパフォーマンスの古典的な問題です。ほとんどすべての開発者が従う経験則では、両方を狙うべきですが、両者が衝突する場合は、パフォーマンスよりも保守性を選択してください。そのルールの例外は、パフォーマンスが問題であることがすでに証明されている場合です。この原則を配列と比較すると、リスト、そしてあなたが得るものはこれです:
パフォーマンスの問題が発生するまで、強く型付けされたリストを使用してください。パフォーマンスの問題が発生した場合は、アレイへのドロップアウトがソリューションのパフォーマンスにメリットをもたらすか、メンテナンスの面でソリューションに悪影響を与えるかどうかを決定します。
まだ言及されていないもう1つの状況は、多数の項目があり、それぞれが関連しているが独立している変数の固定された束で構成されている場合です(たとえば、点の座標または3D三角形の頂点)。公開フィールド構造の配列により、その要素を「インプレース」で効率的に変更できます。これは、他のコレクションタイプでは不可能なことです。構造体の配列はその要素をRAMに連続して保持するため、配列要素への順次アクセスは非常に高速です。コードが配列を介して多くの順次パスを作成する必要がある状況では、構造の配列が、クラスオブジェクト参照の配列または他のコレクションよりも2:1だけ優れている場合があります。さらに、
配列はサイズ変更できませんが、使用中の要素の数とともに配列参照をコードに格納し、必要に応じて配列をより大きな配列に置き換えることは難しくありません。あるいは、動作が非常に似ているList<T>
がバッキングストアを公開するタイプのコードを簡単に記述して、MyPoints.Add(nextPoint);
またはのどちらかを言うことができますMyPoints.Items[23].X += 5;
。コードがリストの最後を超えてアクセスしようとした場合、後者は必ずしも例外をスローしないことに注意してください。ただし、使用法は概念的にはと非常に似ていList<T>
ます。
Point[] arr;
場合、コードが言うことが可能ですarr[3].x+=q;
。たとえばList<Point> list
、代わりに言う必要があるでしょうPoint temp=list[3]; temp.x+=q; list[3]=temp;
。List<T>
方法があったら助かりますUpdate<TP>(int index, ActionByRefRef<T,TP> proc, ref TP params)
。そしてコンパイラは回すことができるlist[3].x+=q;
に{list.Update(3, (ref int value, ref int param)=>value+=param, ref q);
はなく、そのような機能は存在しません。
list[0].X += 3;
リストの最初の要素のXプロパティに3を追加します。And list
is List<Point>
and and Point
a class with X and Y properties
.NETのリストは配列のラッパーであり、内部で配列を使用します。リストの操作の時間の複雑さは配列の場合と同じですが、追加されたすべての機能/リストの使いやすさ(自動サイズ変更やリストクラスに付属するメソッドなど)により、オーバーヘッドが少し増えます。非常に最適化されたコードを記述する必要がある場合や、配列を中心に構築された他のコードを使用している場合など、やむを得ない理由がない限り、すべての場合にリストを使用することをお勧めします。
各データ型の機能を比較するのではなく、最も実用的な答えは「違いは、おそらく両方とも実装されているIEnumerable
ため、達成する必要があるものにとっておそらくそれほど重要ではないので、一般的な慣習に従って、List
しない理由があるまでは、その時点でおそらくで配列を使用する理由があるでしょうList
。」
ほとんどの場合、マネージコードでは、マイクロ最適化を心配するよりも、コレクションをできるだけ簡単に操作できるようにしたいとします。
人気がないかもしれませんが、私はゲームプロジェクトの配列のファンです。-場合によっては、反復速度が重要になることがあります。要素ごとに多くのことを行わない場合、配列のforeachのオーバーヘッドは大幅に少なくなります-ヘルパー関数を使用すると、追加と削除はそれほど難しくありません-遅いですが、一度だけビルドする場合それは問題ではないかもしれません-ほとんどの場合、余分なメモリの浪費が減ります(構造体の配列では本当に重要です)-ガベージとポインタとポインタ追跡のわずかな減少
そうは言っても、実際には配列よりもリストをはるかに頻繁に使用しますが、それぞれの場所があります。
ラッパーと列挙のオーバーヘッドを最適化できるように、組み込み型のListがあると便利です。
リストの生成は配列よりも簡単です。配列の場合、データの正確な長さを知る必要がありますが、リストの場合、データサイズは任意です。また、リストを配列に変換できます。
List<URLDTO> urls = new List<URLDTO>();
urls.Add(new URLDTO() {
key = "wiki",
url = "https://...",
});
urls.Add(new URLDTO()
{
key = "url",
url = "http://...",
});
urls.Add(new URLDTO()
{
key = "dir",
url = "https://...",
});
// convert a list into an array: URLDTO[]
return urls.ToArray();
誰も言及していないため:C#では、配列はリストです。MyClass[]
そして、List<MyClass>
の両方を実装IList<MyClass>
。(例:またはのvoid Foo(IList<int> foo)
ように呼び出すことができます)Foo(new[] { 1, 2, 3 })
Foo(new List<int> { 1, 2, 3 })
したがって、List<MyClass>
引数としてaを受け入れるが機能のサブセットのみを使用するメソッドを作成している場合はIList<MyClass>
、呼び出し元の便宜のために代わりにとして宣言することができます。
詳細:
List
、IList
インターフェースを実装するだけです。
データ構造が必要とされるコンテキストに完全に依存します。たとえば、Listを使用して他の機能またはサービスで使用されるアイテムを作成する場合は、それを行うのに最適な方法です。
アイテムのリストがあり、それらを表示したいだけの場合は、Webページの配列に、使用する必要のあるコンテナがあるとします。
IEnumerable<T>
です。
その場でキャストを行う能力について言及する価値があります。
interface IWork { }
class Foo : IWork { }
void Test( )
{
List<Foo> bb = new List<Foo>( );
// Error: CS0029 Cannot implicitly convert type 'System.Collections.Generic.List<Foo>' to 'System.Collections.Generic.List<IWork>'
List<IWork> cc = bb;
Foo[] bbb = new Foo[4];
// Fine
IWork[] ccc = bbb;
}
そのため、Arrayを関数の戻り値の型または引数で使用すると、柔軟性が少し向上します。
IWork[] GetAllWorks( )
{
List<Foo> fooWorks = new List<Foo>( );
return fooWorks.ToArray( ); // Fine
}
void ExecuteWorks( IWork[] works ) { } // Also accept Foo[]