C#のArrayListとList <>


412

違いは何であるArrayListList<>C#では?

そのだけであるList<>一方で型を持っていArrayListないのですか?



5
近い質問ですが、完全に重複しているとは思いません。これはList<>一般的に尋ねられますが、List<object>具体的には尋ねられます
goodeye

この非常に役立つブログを見つけました、それは役立つかもしれません。:思想私は、リンクを共有する必要があり fintechexplained.blogspot.co.uk/2017/07/...
InfoLearner

回答:


533

はい、ほとんど。List<T>ジェネリッククラスです。キャストを行わずに特定の型の値を格納することをサポートしますobject(この場合T、値の型のArrayList場合、ボックス化/ボックス化解除のオーバーヘッドが発生します)。ArrayList単にobject参照を保存します。ジェネリックコレクションとして、ジェネリックインターフェイスをList<T>実装し、IEnumerable<T>LINQで簡単に使用できます(CastまたはOfType呼び出しを必要としません)。

ArrayListC#にジェネリックがなかった時代に属しています。の代わりに非推奨になりましたList<T>。あなたは使用しないでくださいArrayList目標は、.NET> = 2.0あなたはそれを使用して、古いAPIとのインターフェースに持っていない限りという新しいコードで。


「キャスティング」ではなく「ボクシング」を使用した理由を説明していただけませんか。ここでどんなボクシングが起こりますか?オブジェクトは割り当て/割り当て解除されていますか?
Benjamin Gruenbaum 2013年

2
@BenjaminGruenbaumキャストはより一般的であることは正しいです。とは言っても、実行時の本当の違いは、値の型を処理しているときです( "ボクシング"を書いたときに想定したものです)。参照型の場合、動作はArrayList実行時と実質的に同じです。ただし、静的には、を使用したキャストが必要になりますArrayList
Mehrdad Afshari 2013年

ArrayListが暗黙的にそれを許可しているため、フレームワークがTを「オブジェクト」タイプに制限する必要があるかどうか疑問に思いました。
rajibdotnet 2017

型指定のないコレクションの非推奨については、ジェネリックが有害と
見なされる

@ Ant_222、そのブログは15年近く前に書かれました。過去10年間の証拠から、ジェネリック医薬品は有害ではないことがわかりました。:)
Scott Adams

101

を使用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からプルするときにタイプをチェックして、キャストエラーを防ぐことができます。現在、人々はオブジェクトを使用しているため、ArrayListは不要になりました。
2013年

1
正当化に+1しますが、エラーを回避するために配列リストにif(num is int){}を実行できます
ミナガブリエル14

キャストエラーとボクシングのオーバーヘッドを防ぎます。一般的なジェネリックのほとんどの理由。
marsze 2018年

26

上記のポイントに追加します。使用してArrayList64ビットのオペレーティングシステムでは、32ビットオペレーティングシステムで使用するよりも2倍のメモリを取ります。その間、ジェネリックリストList<T>は、よりもはるかに少ないメモリを使用しArrayListます。

たとえばArrayList、32ビットで19MB を使用すると、64ビットでは39MB必要になります。しかしList<int>、32ビットで8 MBの一般的なリストがある場合、64ビットで8.1 MBしかかかりません。これは、ArrayListと比較すると、481%という大きな違いです。

ソース:プリミティブ型と64ビットのArrayListと汎用リスト


5
これは、参照型ではなく、値型を格納する場合にのみ当てはまります。違いは、arraylistに含めることができるのはポインタのみであり、データ自体を別の場所に格納する必要があるためです。一方、値タイプはリストに直接格納できます。
Rasmus Damgaard Nielsen 2015

19

追加するもう1つの違いは、スレッドの同期に関するものです。

ArrayListコレクションのスレッドセーフラッパーを返すSynchronizedプロパティを通じて、スレッドセーフを提供します。ラッパーは、追加または削除操作のたびにコレクション全体をロックすることによって機能します。したがって、コレクションにアクセスしようとする各スレッドは、その順番が1つのロックを取得するまで待機する必要があります。これはスケーラブルではなく、大規模なコレクションのパフォーマンスを大幅に低下させる可能性があります。

List<T>スレッドの同期は提供されません。アイテムが複数のスレッドで同時に追加または削除される場合、ユーザーコードはすべての同期を提供する必要があります。

詳細はこちら.Net Frameworkのスレッド同期


ArrayList避けることができるなら使うべきだと言っているわけではありませんが、これはばかげた理由です。結局のところ、ラッパーは完全にオプションです。ロックが必要ない場合、またはより詳細な制御が必要な場合は、ラッパーを使用しないでください。
Thorarin 2017年

1
スレッドセーフが必要な場合は、ArrayListを検討する前にSystem.Collections.Concurrent名前空間を確認することをお勧めします。
Ykok 2017年

15

簡単な答えは、

ArrayListは非ジェネリックです

  • これはオブジェクトタイプであるため、任意のデータタイプを格納できます。
  • ArrayListには、文字列、int、employee、objectなどの値(値タイプまたは参照タイプ)を格納できます。(注意と)
  • ボクシングとアンボクシングが行われます。
  • タイプセーフではありません。
  • 古いです。

リストは一般的です

  • これはタイプのタイプなので、ランタイムにTを指定できます。
  • 宣言に基づいて、タイプTの唯一の値(文字列、int、従業員、またはオブジェクト)を格納できます。(注意または)
  • ボクシングとアンボクシングは行われません。
  • タイプセーフ。
  • 新しいです。

例:

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/




2

パフォーマンスは差別化要因としてすでにいくつかの回答で言及されていますが、「どのくらい遅いArrayListですか?」と「全体的に遅いのはなぜですか?」」、以下をご覧ください。

値の型が要素として使用される場合は常に、パフォーマンスが劇的に低下しArrayListます。単に要素を追加する場合を考えてみましょう。ボクシングが進行しているため、ArrayList「追加」はobjectパラメーターのみを受け取るため、ガベージコレクターはトリガーよりも多くの作業を実行しList<T>ます。

時間差はどれくらいですか?と比べて少なくとも数倍遅いList<T>ArrayListvsに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つのガベージコレクションが必要でした。


1

私は、間の違いを考えるArrayListList<T>、次のとおりです。

  1. List<T>、ここでTはvalue-typeであり、よりも高速ですArrayList。これは、List<T>ボックス化/ボックス化解除(Tは値型)を回避するためです。
  2. 多くの情報源によると-通常ArrayListは下位互換性のためだけに使用されます。(本当の違いはありませんが、それは重要なメモだと思います)。
  3. リフレクションは、非ジェネリックと簡単ですArrayListその後、List<T>
  4. ArrayListIsSynchronizedプロパティがあります。したがって、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
  5. ArrayList有するArrayList.SyncRootsyncronisation(のために使用することができるプロパティ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)
        {
            // ...
        }
    }

0

.NET Frameworkのドキュメントで述べたように

ArrayList新規開発のためにクラスを使用することはお勧めしません。代わりに、ジェネリックList<T> クラスを使用することをお勧めします。このArrayListクラスは、異種のオブジェクトのコレクションを保持するように設計されています。ただし、常に最高のパフォーマンスが得られるとは限りません。代わりに、以下をお勧めします。

  • 異種のオブジェクトのコレクションの場合は、List<Object>(C#で)またはList(Of Object)(Visual Basicで)タイプを使用します。
  • オブジェクトの同種のコレクションには、List<T>クラスを使用します。

非ジェネリックコレクションは使用しないでくださいも参照してください

表は、非ジェネリックコレクションタイプをジェネリックコレクションに置き換える方法を示しています


-2

「リスト」を使用すると、キャストエラーを防ぐことができます。ランタイムキャストエラーを回避することは非常に便利です。

例:

ここで(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.
        }
    }

これは、3年前に与えられた回答条件を超えて何を追加しますか?これは、など、適切にフォーマットせずに、ソースにリンクせず、そのままほぼ同じテキストを持っている
ダグラスZareを

-3

私にとって、あなたのデータを知ることがすべてです。効率に基づいてコードを拡張し続けている場合、データ型を解読する方法としてリストタイプを選択する必要があります。その際、タイプ、特に「カスタムタイプ」について常に疑問に思っている不要な手順はありません。マシンが違いを理解し、私が実際に処理しているデータのタイプを判断できる場合、「IF THEN ELSE」の決定の旋回に邪魔されて時間を無駄にする必要があるのはなぜですか?私の哲学は、私が機械で作業するのではなく、私のために機械を機能させることです?さまざまなオブジェクトコードコマンドの独自の違いを理解することは、コードを効率的にするのに大いに役立ちます。

トムジョンソン(1つのエントリ... 1つの出口)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.