違いは何であるArrayList
とList<>
C#では?
そのだけであるList<>
一方で型を持っていArrayList
ないのですか?
List<>
一般的に尋ねられますが、List<object>
具体的には尋ねられます
違いは何であるArrayList
とList<>
C#では?
そのだけであるList<>
一方で型を持っていArrayList
ないのですか?
List<>
一般的に尋ねられますが、List<object>
具体的には尋ねられます
回答:
はい、ほとんど。List<T>
ジェネリッククラスです。キャストを行わずに特定の型の値を格納することをサポートしますobject
(この場合T
、値の型のArrayList
場合、ボックス化/ボックス化解除のオーバーヘッドが発生します)。ArrayList
単にobject
参照を保存します。ジェネリックコレクションとして、ジェネリックインターフェイスをList<T>
実装し、IEnumerable<T>
LINQで簡単に使用できます(Cast
またはOfType
呼び出しを必要としません)。
ArrayList
C#にジェネリックがなかった時代に属しています。の代わりに非推奨になりましたList<T>
。あなたは使用しないでくださいArrayList
目標は、.NET> = 2.0あなたはそれを使用して、古いAPIとのインターフェースに持っていない限りという新しいコードで。
ArrayList
実行時と実質的に同じです。ただし、静的には、を使用したキャストが必要になりますArrayList
。
を使用List<T>
すると、キャストエラーを防ぐことができます。ランタイムキャストエラーを回避することは非常に便利です。
例:
ここでは(を使用してArrayList
)このコードをコンパイルできますが、後で実行エラーが表示されます。
ArrayList array1 = new ArrayList();
array1.Add(1);
array1.Add("Pony"); //No error at compile process
int total = 0;
foreach (int num in array1)
{
total += num; //-->Runtime Error
}
を使用するとList
、次のエラーを回避できます。
List<int> list1 = new List<int>();
list1.Add(1);
//list1.Add("Pony"); //<-- Error at compile process
int total = 0;
foreach (int num in list1 )
{
total += num;
}
リファレンス: MSDN
上記のポイントに追加します。使用してArrayList
64ビットのオペレーティングシステムでは、32ビットオペレーティングシステムで使用するよりも2倍のメモリを取ります。その間、ジェネリックリストList<T>
は、よりもはるかに少ないメモリを使用しArrayList
ます。
たとえばArrayList
、32ビットで19MB を使用すると、64ビットでは39MB必要になります。しかしList<int>
、32ビットで8 MBの一般的なリストがある場合、64ビットで8.1 MBしかかかりません。これは、ArrayListと比較すると、481%という大きな違いです。
追加するもう1つの違いは、スレッドの同期に関するものです。
ArrayList
コレクションのスレッドセーフラッパーを返すSynchronizedプロパティを通じて、スレッドセーフを提供します。ラッパーは、追加または削除操作のたびにコレクション全体をロックすることによって機能します。したがって、コレクションにアクセスしようとする各スレッドは、その順番が1つのロックを取得するまで待機する必要があります。これはスケーラブルではなく、大規模なコレクションのパフォーマンスを大幅に低下させる可能性があります。
List<T>
スレッドの同期は提供されません。アイテムが複数のスレッドで同時に追加または削除される場合、ユーザーコードはすべての同期を提供する必要があります。
詳細はこちら.Net Frameworkのスレッド同期
ArrayList
避けることができるなら使うべきだと言っているわけではありませんが、これはばかげた理由です。結局のところ、ラッパーは完全にオプションです。ロックが必要ない場合、またはより詳細な制御が必要な場合は、ラッパーを使用しないでください。
簡単な答えは、
ArrayList arrayList = new ArrayList();
List<int> list = new List<int>();
arrayList.Add(1);
arrayList.Add("String");
arrayList.Add(new object());
list.Add(1);
list.Add("String"); // Compile-time Error
list.Add(new object()); // Compile-time Error
Microsoftの公式ドキュメントをお読みください:https : //blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/
注:違いを理解する前にジェネリックを知っておく必要があります:https : //docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
ArrayList
は、さまざまなタイプのデータList<>
のコレクションですが、独自の依存関係の同様のタイプのコレクションです。
パフォーマンスは差別化要因としてすでにいくつかの回答で言及されていますが、「どのくらい遅いArrayList
ですか?」と「全体的に遅いのはなぜですか?」」、以下をご覧ください。
値の型が要素として使用される場合は常に、パフォーマンスが劇的に低下しArrayList
ます。単に要素を追加する場合を考えてみましょう。ボクシングが進行しているため、ArrayList
「追加」はobject
パラメーターのみを受け取るため、ガベージコレクターはトリガーよりも多くの作業を実行しList<T>
ます。
時間差はどれくらいですか?と比べて少なくとも数倍遅いList<T>
。ArrayList
vsに10 milのint値を追加するコードで何が起こるかを見てみましょうList<T>
。
これは実行時間の5倍の差ですは、「平均」列のになり、黄色で強調表示されています。また、赤で強調表示された、それぞれに対して実行されたガベージコレクションの数の違いにも注意してください(GCなし/ 1000回の実行)。
プロファイラーを使用して状況をすばやく確認すると、実際に要素を追加するのではなく、ほとんどの時間がGCに費やされていることがわかります。以下の茶色のバーは、ガベージコレクタのアクティビティのブロックを表しています。
上記のArrayList
シナリオで何が起こっているかの詳細な分析をここに書いていますhttps://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/。
同様の結果は、Jeffrey Richterによる「CLR via C#」にもあります。第12章(ジェネリック)から:
[…]私のコンピューターでこのプログラムのリリースビルド(最適化をオンにした状態)をコンパイルして実行すると、次の出力が得られます。
00:00:01.6246959(GCs = 6)List <Int32>
00:00:10.8555008(GCs = 390)Int32のArrayList
00:00:02.5427847(GCs = 4)List <String>
00:00:02.7944831(GCs = 7 )文字列のArrayListここでの出力は、Int32型でジェネリックリストアルゴリズムを使用すると、Int32で非ジェネリックArrayListアルゴリズムを使用するよりもはるかに高速であることを示しています。実際、その差は驚異的です。1.6秒とほぼ11秒です。それは〜7倍高速です!さらに、ArrayListで値型(Int32)を使用すると、多くのボックス化操作が発生し、390ガベージコレクションが発生します。一方、リストアルゴリズムでは6つのガベージコレクションが必要でした。
私は、間の違いを考えるArrayList
とList<T>
、次のとおりです。
List<T>
、ここでTはvalue-typeであり、よりも高速ですArrayList
。これは、List<T>
ボックス化/ボックス化解除(Tは値型)を回避するためです。ArrayList
は下位互換性のためだけに使用されます。(本当の違いはありませんが、それは重要なメモだと思います)。ArrayList
その後、List<T>
ArrayList
IsSynchronized
プロパティがあります。したがって、syncronisedを作成して使用するのは簡単ArrayList
です。のIsSynchronized
物件が見つかりませんでしたList<T>
。また、このタイプの同期は比較的非効率的です(msdn)。
var arraylist = new ArrayList();
var arrayListSyncronized = ArrayList.Synchronized(arraylist
Console.WriteLine($"syncronized {arraylist.IsSynchronized}");
Console.WriteLine($"syncronized {arrayListSyncronized.IsSynchronized}");
var list = new List<object>();
var listSyncronized = ArrayList.Synchronized(list);
Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
ArrayList
有するArrayList.SyncRoot
syncronisation(のために使用することができるプロパティMSDNを)。List<T>
はSyncRoot
プロパティを持っていないので、次の構成では、を使用する場合にオブジェクトを使用する必要がありますList<T>
。
ArrayList myCollection = new ArrayList();
lock(myCollection.SyncRoot) // ofcourse you can use another object for this goal
{
foreach (object item in myCollection)
{
// ...
}
}
.NET Frameworkのドキュメントで述べたように
ArrayList
新規開発のためにクラスを使用することはお勧めしません。代わりに、ジェネリックList<T>
クラスを使用することをお勧めします。このArrayList
クラスは、異種のオブジェクトのコレクションを保持するように設計されています。ただし、常に最高のパフォーマンスが得られるとは限りません。代わりに、以下をお勧めします。
- 異種のオブジェクトのコレクションの場合は、
List<Object>
(C#で)またはList(Of Object)
(Visual Basicで)タイプを使用します。- オブジェクトの同種のコレクションには、
List<T>
クラスを使用します。
非ジェネリックコレクションは使用しないでくださいも参照してください
「リスト」を使用すると、キャストエラーを防ぐことができます。ランタイムキャストエラーを回避することは非常に便利です。
例:
ここで(ArrayListを使用して)このコードをコンパイルできますが、後で実行エラーが表示されます。
// Create a new ArrayList
System.Collections.ArrayList mixedList = new System.Collections.ArrayList();
// Add some numbers to the list
mixedList.Add(7);
mixedList.Add(21);
// Add some strings to the list
mixedList.Add("Hello");
mixedList.Add("This is going to be a problem");
System.Collections.ArrayList intList = new System.Collections.ArrayList();
System.Collections.ArrayList strList = new System.Collections.ArrayList();
foreach (object obj in mixedList)
{
if (obj.GetType().Equals(typeof(int)))
{
intList.Add(obj);
}
else if (obj.GetType().Equals(typeof(string)))
{
strList.Add(obj);
}
else
{
// error.
}
}
私にとって、あなたのデータを知ることがすべてです。効率に基づいてコードを拡張し続けている場合、データ型を解読する方法としてリストタイプを選択する必要があります。その際、タイプ、特に「カスタムタイプ」について常に疑問に思っている不要な手順はありません。マシンが違いを理解し、私が実際に処理しているデータのタイプを判断できる場合、「IF THEN ELSE」の決定の旋回に邪魔されて時間を無駄にする必要があるのはなぜですか?私の哲学は、私が機械で作業するのではなく、私のために機械を機能させることです?さまざまなオブジェクトコードコマンドの独自の違いを理解することは、コードを効率的にするのに大いに役立ちます。
トムジョンソン(1つのエントリ... 1つの出口)