Да, в значительной степени. List<T>это общий класс. Он поддерживает хранение значений определенного типа без приведения к типу или к нему object(что может привести к накладным расходам на упаковку / распаковку, когда Tв данном ArrayListслучае используется тип значения ). ArrayListпросто хранит objectссылки. В качестве универсальной коллекции, List<T>реализует общий IEnumerable<T>интерфейс и может быть легко использован в LINQ (без необходимости какого - либо CastилиOfType вызова, вызова).
ArrayListотносится к тем дням, когда у C # не было дженериков. Это не рекомендуется в пользу List<T>. Вы не должны использовать ArrayListв новом коде, предназначенном для .NET> = 2.0, если вам не нужно взаимодействовать со старым API, который его использует.
Не могли бы вы объяснить, почему вы использовали «бокс», а не «кастинг»? Какой бокс здесь происходит? Распределяются / освобождаются ли объекты?
Бенджамин Грюнбаум
2
@BenjaminGruenbaum Вы правы, что кастинг будет более общим. Тем не менее, реальная разница во время выполнения состоит в том, что вы имеете дело с типами значений (что я и предполагал, когда писал «бокс»). Для ссылочных типов поведение фактически такое же, как ArrayListво время выполнения. Статически, хотя, это потребует бросок с ArrayList.
Мехрдад Афшари
Мне было интересно, должен ли фреймворк ограничивать T типом «объект», поскольку ArrayList неявно допускает это.
Раджибдотнет
Относительно устаревания нетипизированных коллекций см.
Обобщенные сведения, считающиеся
@ Ant_222, этот блог был написан почти 15 лет назад. Я думаю, что данные за последнее десятилетие показали, что генерики не являются вредными. :)
Скотт Адамс
101
Используя List<T>вы можете предотвратить ошибки приведения. Это очень полезно, чтобы избежать ошибки приведения во время выполнения .
Пример:
Здесь (используя ArrayList) вы можете скомпилировать этот код, но позже вы увидите ошибку выполнения.
ArrayList array1 =newArrayList();
array1.Add(1);
array1.Add("Pony");//No error at compile processint total =0;foreach(int num in array1){
total += num;//-->Runtime Error}
Если вы используете List, вы избежите этих ошибок:
List<int> list1 =newList<int>();
list1.Add(1);//list1.Add("Pony"); //<-- Error at compile processint total =0;foreach(int num in list1 ){
total += num;}
Вы можете проверить тип при извлечении из ArrayList, чтобы предотвратить ошибки приведения. Теперь люди используют объект, что делает ArrayList более не нужным.
Переключить
1
я +1 к обоснованию, но вы все еще можете сделать, если (num is int) {} в ваш список массивов, чтобы избежать ошибок
Mina Gabriel
Предотвращение ошибок приведения и накладных расходов на бокс. Довольно много причин для дженериков в целом.
Марш
26
Чтобы добавить к вышеуказанным пунктам. Использование ArrayListв 64-битной операционной системе занимает в 2 раза больше памяти, чем в 32-битной операционной системе. Между тем, общий список List<T>будет использовать гораздо меньше памяти, чем ArrayList.
например, если мы используем ArrayList19 МБ в 32-разрядной версии, то в 64-разрядной системе потребуется 39 МБ. Но если у вас есть общий список List<int>8 МБ в 32-битной версии, то для 64-битной версии потребуется всего 8,1 МБ, что составляет колоссальную разницу в 481% по сравнению с ArrayList.
это верно только для хранения типов значений, а не ссылочных типов. Разница заключается в том, что массив данных может содержать только указатели, а сами данные должны храниться в другом месте. С другой стороны, типы значений могут храниться непосредственно в списке.
Расмус Дамгаард Нильсен
19
Еще одно отличие, которое нужно добавить, касается синхронизации потоков.
ArrayListобеспечивает некоторую поточную безопасность через свойство Synchronized, которое возвращает поточно-ориентированную оболочку вокруг коллекции. Оболочка работает, блокируя всю коллекцию при каждой операции добавления или удаления. Поэтому каждый поток, который пытается получить доступ к коллекции, должен ждать своей очереди, чтобы взять одну блокировку. Это не масштабируется и может привести к значительному снижению производительности для больших коллекций.
List<T>не обеспечивает синхронизацию потоков; Пользовательский код должен обеспечивать всю синхронизацию, когда элементы добавляются или удаляются в нескольких потоках одновременно.
Я не говорю, что вы должны использовать, ArrayListесли этого можно избежать, но это глупая причина. В конце концов, обертка совершенно необязательна; если вам не нужна блокировка или если вам нужен более детальный контроль, не используйте оболочку.
Торарин
1
Если вам нужна безопасность потоков, я предлагаю взглянуть на пространство имен System.Collections.Concurrent, прежде чем рассматривать ArrayList.
Йок
15
Простой ответ:
ArrayList не является универсальным
Это тип объекта, поэтому вы можете хранить в нем любой тип данных.
Вы можете хранить любые значения (тип значения или ссылочный тип), такие как строка, int, employee и object, в ArrayList. (Примечание и)
Бокс и распаковка случится.
Не тип безопасно.
Это старше.
Список является общим
Это тип типа, так что вы можете указать T во время выполнения.
Вы можете хранить единственное значение типа T (строка или int, сотрудник или объект) на основе объявления. (Примечание или)
Производительность уже упоминалась в нескольких ответах как отличительный фактор, но для решения вопроса « Насколько медленнее ArrayList? »И« Почему это в целом медленнее?Посмотрите ниже.
Всякий раз, когда типы значений используются в качестве элементов, производительность резко падает ArrayList. Рассмотрим случай простого добавления элементов. Из-за происходящего бокса - поскольку ArrayListAdd добавляет только objectпараметры - сборщик мусора запускается для выполнения гораздо большего количества работы, чем с List<T>.
Сколько разница во времени? По крайней мере, в несколько раз медленнее, чем с List<T>. Достаточно взглянуть на то, что происходит с кодом, добавляющим значения 10 mil int к ArrayListvs List<T>:
Это разница во времени выполнения 5x в столбце «Среднее», выделенная желтым цветом. Обратите внимание также на разницу в количестве сборок мусора, выполненных для каждой, выделены красным (нет GCs / 1000 прогонов).
Использование профилировщика для быстрого просмотра происходящего показывает, что большую часть времени тратится на сборку мусора , а не на добавление элементов. Коричневые столбики ниже представляют блокирование активности сборщика мусора:
Подобные выводы содержатся в «CLR via C #» Джеффри Рихтера. Из главы 12 (Обобщение):
[…] Когда я компилирую и запускаю на своем компьютере сборку релиза (с включенной оптимизацией) этой программы, я получаю следующий вывод.
00: 00: 01.6246959 (GCs = 6) Список <Int32> 00: 00: 10.8555008 (GC = 390) ArrayList из Int32
00: 00: 02.5427847 (GCs = 4) Список <String>
00: 00: 02.7944831 (GCs = 7 ) ArrayList of String
Вывод здесь показывает, что использование универсального алгоритма List с типом Int32 намного быстрее, чем использование неуниверсального алгоритма ArrayList с Int32. На самом деле разница феноменальная: 1,6 секунды против почти 11 секунд. Это в 7 раз быстрее ! Кроме того, использование типа значения (Int32) с ArrayList вызывает много операций бокса, что приводит к 390 сборкам мусора. Между тем, алгоритм List требует 6 сборок мусора.
Я думаю, что различия между ArrayListи List<T>являются:
List<T>где T является типом значения быстрее, чем ArrayList. Это потому, что List<T>избегает упаковки / распаковки (где T - тип значения).
Многие источники говорят - обычно ArrayListиспользуются только для обратной совместимости. (это не реальная разница, но я думаю, что это важное примечание).
Отражение легче с необщей ArrayListзатемList<T>
ArrayListимеет IsSynchronizedсвойство. Таким образом, легко создавать и использовать синхронизированные ArrayList. Я не нашел IsSynchronizedнедвижимость для List<T>. Также имейте в виду, что этот тип синхронизации относительно неэффективен, msdn ):
var arraylist =newArrayList();var arrayListSyncronized =ArrayList.Synchronized(arraylist
Console.WriteLine($"syncronized {arraylist.IsSynchronized}");Console.WriteLine($"syncronized {arrayListSyncronized.IsSynchronized}");varlist=newList<object>();var listSyncronized =ArrayList.Synchronized(list);Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such propConsole.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
ArrayListимеет ArrayList.SyncRootсвойство, которое можно использовать для синхронизации ( msdn ). List<T>не имеетSyncRoot property, поэтому в следующей конструкции вам нужно использовать какой-то объект, если вы используете List<T>:
ArrayList myCollection =newArrayList();lock(myCollection.SyncRoot)// ofcourse you can use another object for this goal{foreach(object item in myCollection){// ...}}
Мы не рекомендуем использовать этот ArrayListкласс для новых разработок. Вместо этого мы рекомендуем использовать универсальный List<T>
класс. ArrayListКласс предназначен для хранения разнородных коллекций объектов. Тем не менее, он не всегда предлагает лучшую производительность. Вместо этого мы рекомендуем следующее:
Для гетерогенной коллекции объектов используйте List<Object>List(Of Object) тип (в C #) или (в Visual Basic).
Для однородной коллекции объектов используйте List<T>класс.
Используя «Список», вы можете предотвратить ошибки приведения. Это очень полезно, чтобы избежать ошибки приведения во время выполнения.
Пример:
Здесь (используя ArrayList) вы можете скомпилировать этот код, но позже вы увидите ошибку выполнения.
// Create a new ArrayListSystem.Collections.ArrayList mixedList =newSystem.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 =newSystem.Collections.ArrayList();System.Collections.ArrayList strList =newSystem.Collections.ArrayList();foreach(object obj in mixedList){if(obj.GetType().Equals(typeof(int))){
intList.Add(obj);}elseif(obj.GetType().Equals(typeof(string))){
strList.Add(obj);}else{// error.}}
Что это добавляет к ответу, который дал Терма три года назад? У него почти одинаковый дословный текст, без ссылки на источник, без правильного форматирования и т. Д.
Дуглас Заре
-3
Для меня это все о знании ваших данных. Если я продолжу расширять свой код на основе эффективности, мне придется выбрать опцию «Список» как способ расшифровки моих данных без ненужного шага, который всегда интересует типы, особенно «Пользовательские типы». Если машина понимает разницу и может определить, с каким типом данных я на самом деле имею дело, тогда почему я должен мешать и тратить время на размышления «ЕСЛИ ТАК ЕЩЕ»? Моя философия - позволить машине работать вместо меня, а я работаю над ней? Знание уникальных различий различных команд объектного кода имеет большое значение для повышения эффективности вашего кода.
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
) вы можете скомпилировать этот код, но позже вы увидите ошибку выполнения.Если вы используете
List
, вы избежите этих ошибок:Ссылка: MSDN
источник
Чтобы добавить к вышеуказанным пунктам. Использование
ArrayList
в 64-битной операционной системе занимает в 2 раза больше памяти, чем в 32-битной операционной системе. Между тем, общий списокList<T>
будет использовать гораздо меньше памяти, чемArrayList
.например, если мы используем
ArrayList
19 МБ в 32-разрядной версии, то в 64-разрядной системе потребуется 39 МБ. Но если у вас есть общий списокList<int>
8 МБ в 32-битной версии, то для 64-битной версии потребуется всего 8,1 МБ, что составляет колоссальную разницу в 481% по сравнению с ArrayList.Источник: ArrayList против универсального списка для примитивных типов и 64-битных
источник
Еще одно отличие, которое нужно добавить, касается синхронизации потоков.
Более подробная информация здесь Синхронизация потоков в .Net Framework
источник
ArrayList
если этого можно избежать, но это глупая причина. В конце концов, обертка совершенно необязательна; если вам не нужна блокировка или если вам нужен более детальный контроль, не используйте оболочку.Простой ответ:
ArrayList не является универсальным
Список является общим
Пример:
Пожалуйста, прочитайте официальный документ 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
не безопасны, тогдаList<T>
как безопасны. Просто :).источник
Производительность уже упоминалась в нескольких ответах как отличительный фактор, но для решения вопроса « Насколько медленнее
ArrayList
? »И« Почему это в целом медленнее?Посмотрите ниже.Всякий раз, когда типы значений используются в качестве элементов, производительность резко падает
ArrayList
. Рассмотрим случай простого добавления элементов. Из-за происходящего бокса - посколькуArrayList
Add добавляет толькоobject
параметры - сборщик мусора запускается для выполнения гораздо большего количества работы, чем сList<T>
.Сколько разница во времени? По крайней мере, в несколько раз медленнее, чем с
List<T>
. Достаточно взглянуть на то, что происходит с кодом, добавляющим значения 10 mil int кArrayList
vsList<T>
:Это разница во времени выполнения 5x в столбце «Среднее», выделенная желтым цветом. Обратите внимание также на разницу в количестве сборок мусора, выполненных для каждой, выделены красным (нет GCs / 1000 прогонов).
Использование профилировщика для быстрого просмотра происходящего показывает, что большую часть времени тратится на сборку мусора , а не на добавление элементов. Коричневые столбики ниже представляют блокирование активности сборщика мусора:
Я написал подробный анализ того, что происходит с вышеописанным
ArrayList
сценарием, здесь https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/ .Подобные выводы содержатся в «CLR via C #» Джеффри Рихтера. Из главы 12 (Обобщение):
источник
Я думаю, что различия между
ArrayList
иList<T>
являются:List<T>
где T является типом значения быстрее, чемArrayList
. Это потому, чтоList<T>
избегает упаковки / распаковки (где T - тип значения).ArrayList
используются только для обратной совместимости. (это не реальная разница, но я думаю, что это важное примечание).ArrayList
затемList<T>
ArrayList
имеетIsSynchronized
свойство. Таким образом, легко создавать и использовать синхронизированныеArrayList
. Я не нашелIsSynchronized
недвижимость дляList<T>
. Также имейте в виду, что этот тип синхронизации относительно неэффективен, msdn ):ArrayList
имеетArrayList.SyncRoot
свойство, которое можно использовать для синхронизации ( msdn ).List<T>
не имеетSyncRoot
property, поэтому в следующей конструкции вам нужно использовать какой-то объект, если вы используетеList<T>
:источник
Как упомянуто в документации .NET Framework
Смотрите также Не общие коллекции не должны использоваться
источник
Используя «Список», вы можете предотвратить ошибки приведения. Это очень полезно, чтобы избежать ошибки приведения во время выполнения.
Пример:
Здесь (используя ArrayList) вы можете скомпилировать этот код, но позже вы увидите ошибку выполнения.
источник
Для меня это все о знании ваших данных. Если я продолжу расширять свой код на основе эффективности, мне придется выбрать опцию «Список» как способ расшифровки моих данных без ненужного шага, который всегда интересует типы, особенно «Пользовательские типы». Если машина понимает разницу и может определить, с каким типом данных я на самом деле имею дело, тогда почему я должен мешать и тратить время на размышления «ЕСЛИ ТАК ЕЩЕ»? Моя философия - позволить машине работать вместо меня, а я работаю над ней? Знание уникальных различий различных команд объектного кода имеет большое значение для повышения эффективности вашего кода.
Том Джонсон (один вход ... один выход)
источник