ArrayList vs List <> en C #

412

Quelle est la différence entre ArrayListet List<>en C #?

Est-ce seulement celui qui List<>a un type alors ArrayListque non?

scatman
la source
5
doublon possible d' ArrayList vs List <object>
John Saunders
5
C'est une question proche, mais je pense que pas exactement en double. Cela pose des questions sur List<>en général, alors que l'on pose des questions sur List<object>spécifiquement
revoir
J'ai trouvé ce blog très utile, cela pourrait aider. J'ai pensé que je devrais partager le lien: fintechexplained.blogspot.co.uk/2017/07/…
InfoLearner

Réponses:

533

Oui, à peu près. List<T>est une classe générique. Il prend en charge le stockage de valeurs d'un type spécifique sans transtypage vers ou à partir de object(ce qui aurait entraîné des frais généraux de boxe / unboxing alors qu'il Ts'agit d'un type de valeur dans le ArrayListcas). ArrayListstocke simplement les objectréférences. En tant que collection générique, List<T>implémente l' IEnumerable<T>interface générique et peut être utilisée facilement dans LINQ (sans nécessiter Castni OfTypeappel).

ArrayListappartient à l'époque où C # n'avait pas de génériques. Il est déconseillé en faveur de List<T>. Vous ne devez pas utiliser ArrayListdans un nouveau code qui cible .NET> = 2.0, sauf si vous devez vous interfacer avec une ancienne API qui l'utilise.

Mehrdad Afshari
la source
Pourriez-vous expliquer pourquoi vous avez utilisé la «boxe» et non le «casting»? Quelle boxe se passe ici? Les objets sont-ils alloués / désalloués?
Benjamin Gruenbaum
2
@BenjaminGruenbaum Vous avez raison, le casting serait plus général. Cela dit, la vraie différence au moment de l'exécution est lorsque vous avez affaire à des types de valeurs (ce que j'ai supposé quand j'ai écrit "boxing"). Pour les types de référence, le comportement est effectivement le même qu'à l' ArrayListexécution. Mais statiquement, il faudra un casting avec ArrayList.
Mehrdad Afshari
Je me demandais si le framework devait restreindre T à être de type "objet", puisque ArrayList le permet implicitement.
rajibdotnet
En ce qui concerne la dépréciation des collections non typées, voir Generics Considered Harmful
Ant_222
@ Ant_222, ce blog a été écrit il y a près de 15 ans. Je pense que les preuves de la dernière décennie + ont montré que les génériques ne sont pas nocifs. :)
Scott Adams
101

L' utilisation , List<T>vous pouvez éviter les erreurs de coulée. Il est très utile d'éviter une erreur de transtypage d' exécution .

Exemple:

Ici (en utilisant ArrayList), vous pouvez compiler ce code mais vous verrez une erreur d'exécution plus tard.

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
}

Si vous utilisez List, vous évitez ces erreurs:

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;
}

Référence: MSDN

termas
la source
Vous pouvez vérifier le type lorsque vous extrayez de ArrayList pour éviter les erreurs de transtypage. De nos jours, les gens utilisent objet, ce qui rend ArrayList inutile.
Switch
1
i +1 à la justification, mais vous pouvez toujours le faire si (num est int) {} à votre liste de tableaux pour éviter les erreurs
Mina Gabriel
Empêchez les erreurs de casting et les frais généraux de boxe. À peu près les raisons des génériques en général.
marsze
26

Pour ajouter aux points ci-dessus. L'utilisation ArrayListdans le système d'exploitation 64 bits prend 2 fois plus de mémoire que l'utilisation dans le système d'exploitation 32 bits. Pendant ce temps, la liste générique List<T>utilise beaucoup moins de mémoire que le ArrayList.

par exemple, si nous utilisons un ArrayListde 19 Mo en 32 bits, il faudrait 39 Mo en 64 bits. Mais si vous avez une liste générique List<int>de 8 Mo en 32 bits, cela ne prendrait que 8,1 Mo en 64 bits, ce qui représente une différence de 481% par rapport à ArrayList.

La source: ArrayList's vs Liste générique pour les types primitifs et 64 bits

Anoop
la source
5
cela n'est vrai que pour le stockage des types de valeur, pas des types de référence. la différence est due au fait qu'un arraylist ne peut contenir que des pointeurs, et les données elles-mêmes doivent être stockées ailleurs. En revanche, les types de valeurs peuvent être stockés directement dans une liste.
Rasmus Damgaard Nielsen
19

Une autre différence à ajouter concerne la synchronisation des threads.

ArrayListfournit une certaine sécurité des threads via la propriété Synchronized, qui renvoie un wrapper thread-safe autour de la collection. L'encapsuleur fonctionne en verrouillant la collection entière à chaque opération d'ajout ou de suppression. Par conséquent, chaque thread qui tente d'accéder à la collection doit attendre son tour pour prendre le verrou. Ce n'est pas évolutif et peut entraîner une dégradation significative des performances pour les grandes collections.

List<T>ne fournit aucune synchronisation de thread; le code utilisateur doit fournir toute la synchronisation lorsque des éléments sont ajoutés ou supprimés simultanément sur plusieurs threads.

Plus d'informations ici Synchronisation des threads dans le .Net Framework

NullReference
la source
Je ne dis pas que vous devriez l'utiliser ArrayListsi cela peut être évité, mais c'est une raison stupide. L'emballage est entièrement facultatif après tout; si vous n'avez pas besoin de verrouillage ou si vous avez besoin d'un contrôle plus précis, n'utilisez pas le wrapper.
Thorarin
1
Si vous voulez la sécurité des threads, je suggère de regarder l'espace de noms System.Collections.Concurrent avant d'envisager ArrayList.
Ykok
15

La réponse simple est,

ArrayList n'est pas générique

  • Il s'agit d'un type d'objet, vous pouvez donc y stocker n'importe quel type de données.
  • Vous pouvez stocker toutes les valeurs (type de valeur ou type de référence) telles que chaîne, entier, employé et objet dans ArrayList. (Remarque et)
  • La boxe et le déballage auront lieu.
  • Pas de type sûr.
  • C'est plus vieux.

La liste est générique

  • Il s'agit d'un type de type, vous pouvez donc spécifier le T lors de l'exécution.
  • Vous pouvez stocker une seule valeur de type T (chaîne ou entier ou employé ou objet) en fonction de la déclaration. (Remarque ou)
  • La boxe et le déballage ne se produiront pas.
  • Tapez sûr.
  • C'est plus récent.

Exemple:

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

Veuillez lire le document officiel de Microsoft : https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/

entrez la description de l'image ici

Remarque : Vous devez connaître les génériques avant de comprendre la différence: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/

Aravin
la source
4

ArrayListest la collection de données de types différents, tandis que List<>la collection de types similaires de ses propres dépendances.

Law Kant Dayal
la source
3

ArrayListne sont pas de type sécurisé tandis que List<T>sont de type sécurisé. Facile :).

Hassan Rahman
la source
2

La performance a déjà été mentionnée dans plusieurs réponses comme facteur de différenciation, mais pour répondre à la question « Combien est plus lent ArrayList? »Et« Pourquoi est-il globalement plus lent?», Regardez ci-dessous.

Chaque fois que des types de valeurs sont utilisés en tant qu'éléments, les performances diminuent considérablement avec ArrayList. Prenons le cas de l'ajout simple d'éléments. En raison de la boxe en cours - comme ArrayListAdd ne prend que des objectparamètres - le Garbage Collector est déclenché pour effectuer beaucoup plus de travail qu'avec List<T>.

Quelle est la différence de temps? Au moins plusieurs fois plus lentement qu'avec List<T>. Jetez un coup d'œil à ce qui se passe avec le code ajoutant des valeurs int de 10 mil à un ArrayListvs List<T>: entrez la description de l'image ici

C'est une différence de temps d'exécution de 5x dans la colonne `` Moyenne '', surlignée en jaune. Notez également la différence dans le nombre de récupérations effectuées pour chacune, surlignée en rouge (pas de GC / 1000 exécutions).

L'utilisation d'un profileur pour voir ce qui se passe rapidement montre que la plupart du temps est consacré à des GC , au lieu d'ajouter réellement des éléments. Les barres brunes ci-dessous représentent le blocage de l'activité de Garbage Collector: entrez la description de l'image ici

J'ai écrit une analyse détaillée de ce qui se passe avec le ArrayListscénario ci-dessus ici https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/ .

Des résultats similaires se trouvent dans «CLR via C #» de Jeffrey Richter. Du chapitre 12 (Génériques):

[…] Lorsque je compile et exécute une version de build (avec les optimisations activées) de ce programme sur mon ordinateur, j'obtiens la sortie suivante.

00: 00: 01.6246959 (GCs = 6) Liste <Int32>
00: 00: 10.8555008 (GCs = 390) ArrayList of Int32
00: 00: 02.5427847 (GCs = 4) List <String>
00: 00: 02.7944831 (GCs = 7 ) ArrayList of String

La sortie ici montre que l'utilisation de l'algorithme de liste générique avec le type Int32 est beaucoup plus rapide que l'utilisation de l'algorithme ArrayList non générique avec Int32. En fait, la différence est phénoménale: 1,6 seconde contre près de 11 secondes. C'est ~ 7 fois plus rapide ! En outre, l'utilisation d'un type de valeur (Int32) avec ArrayList provoque de nombreuses opérations de boxe, ce qui entraîne 390 récupérations de place. Pendant ce temps, l'algorithme List nécessitait 6 garbage collections.

Mihai Albert
la source
1

Je pense que les différences entre ArrayListet List<T>sont:

  1. List<T>, où T est le type valeur est plus rapide que ArrayList. En effet, List<T>évite la boxe / unboxing (où T est de type valeur).
  2. De nombreuses sources disent - généralement ArrayListutilisé uniquement pour des raisons de compatibilité descendante. (ce n'est pas une vraie différence, mais je pense que c'est une note importante).
  3. La réflexion est plus facile avec non générique , ArrayListpuisList<T>
  4. ArrayLista une IsSynchronizedpropriété. Ainsi, il est facile de créer et d'utiliser synchronisé ArrayList. Je n'ai pas trouvé de IsSynchronizedpropriété pour List<T>. Gardez également à l'esprit que ce type de synchronisation est relativement inefficace, 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. ArrayListpossède une ArrayList.SyncRootpropriété qui peut être utilisée pour la synchronisation ( msdn ). List<T>n'a pas de SyncRootpropriété, donc dans la construction suivante, vous devez utiliser un objet si vous utilisez List<T>:

    ArrayList myCollection = new ArrayList();
    lock(myCollection.SyncRoot) //  ofcourse you can use another object for this goal
    {
        foreach (object item in myCollection)
        {
            // ...
        }
    }
burzhuy
la source
0

Comme mentionné dans la documentation de .NET Framework

Nous vous déconseillons d'utiliser la ArrayListclasse pour de nouveaux développements. Au lieu de cela, nous vous recommandons d'utiliser la List<T> classe générique . La ArrayListclasse est conçue pour contenir des collections hétérogènes d'objets. Cependant, il n'offre pas toujours les meilleures performances. Au lieu de cela, nous recommandons ce qui suit:

  • Pour une collection hétérogène d'objets, utilisez le type List<Object>(en C #) ou List(Of Object)(en Visual Basic).
  • Pour une collection homogène d'objets, utilisez la List<T>classe.

Voir aussi Les collections non génériques ne doivent pas être utilisées

le tableau montre comment les types de collection non génériques peuvent être remplacés par leurs homologues génériques

ElasticCode
la source
-2

En utilisant "Liste", vous pouvez éviter les erreurs de casting. Il est très utile d'éviter une erreur de transtypage d'exécution.

Exemple:

Ici (en utilisant ArrayList), vous pouvez compiler ce code mais vous verrez une erreur d'exécution plus tard.

    // 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.
        }
    }
Deepak
la source
Qu'est-ce que cela ajoute au-delà de la réponse donnée par termas trois ans plus tôt? Il a presque le même texte textuellement, sans lien vers la source, sans mise en forme correcte, etc.
Douglas Zare
-3

Pour moi, il s'agit de connaître vos données. Si je continue à étendre mon code sur la base de l'efficacité, je devrais choisir l'option Liste comme moyen de déchiffrer mes données sans l'étape inutile de toujours me poser des questions sur les types, en particulier les `` types personnalisés ''. Si la machine comprend la différence et peut déterminer sur quel type de données je traite réellement, alors pourquoi devrais-je gêner et perdre du temps à traverser les girations des déterminations `` IF THEN ELSE ''? Ma philosophie est de laisser la machine fonctionner pour moi au lieu de travailler sur la machine? Connaître les différences uniques des différentes commandes de code objet contribue grandement à rendre votre code aussi efficace.

Tom Johnson (une entrée ... une sortie)

user1998271
la source