ArrayList
和List<>
在C#中有什么区别?
仅仅是因为List<>
有一个类型而ArrayList
没有吗?
List<T>
是一种通用类。它支持存储特定类型的值,无需在 object
和 T
是值类型时进行装箱/拆箱(在 ArrayList
的情况下会产生开销) 。ArrayList
仅存储 object
引用。作为一种通用集合,List<T>
实现了通用的 IEnumerable<T>
接口,并且可以轻松地在 LINQ 中使用(无需调用任何 Cast
或 OfType
)。
ArrayList
属于 C# 没有泛型的时代。它已过时,推荐使用 List<T>
。除非必须与使用它的旧 API 进行接口交互,否则不应在面向 .NET >= 2.0 的新代码中使用 ArrayList
。ArrayList
相同。但在静态方面,在使用ArrayList
时需要进行类型转换。 - Mehrdad Afshari使用 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 位操作系统时的两倍。与此同时,泛型列表 List<T>
所占用的内存要比 ArrayList
少得多。
例如,如果我们在 32 位操作系统中使用一个 19MB 的 ArrayList
,那么在 64 位操作系统中就需要占用 39MB 的内存。但是如果你有一个 8MB 的泛型列表 List<int>
在 32 位操作系统中,那么在 64 位操作系统中只需要占用 8.1MB 的内存,这是一个高达 481% 的巨大差异,相较于 ArrayList 来说。
来源:ArrayList’s vs. generic List for primitive types and 64-bits
ArrayList
通过 Synchronized 属性提供了一些线程安全性,它返回一个围绕该集合的线程安全包装器。这个包装器通过在每个添加或删除操作上锁定整个集合来工作。因此,试图访问集合的每个线程必须等待轮到它获取一个锁。这样做不可扩展,并且对于大型集合可能会导致显着的性能降低。
List<T>
不提供任何线程同步;当多个线程同时添加或删除项目时,用户代码必须提供所有同步。
更多信息请参见.Net Framework中的线程同步
ArrayList
,如果可以避免的话,但这个理由很愚蠢。毕竟,包装器是完全可选的;如果你不需要锁定或者需要更细粒度的控制,就不要使用包装器。 - Thorarin简单来说,
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
注意: 在理解区别之前,您应该了解泛型: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
性能已经在几个答案中被提到作为一个区分因素,但是要回答“ArrayList
有多慢?”和“为什么它总体上更慢?”,请看下面。
每当值类型用作元素时,ArrayList
的性能会急剧下降。考虑简单添加元素的情况。由于装箱正在进行-因为ArrayList
的Add只采用参数-垃圾收集器被触发执行比List<T>
更多的工作。
时间差异有多少?至少比List<T>
慢几倍。只需看一下将10百万个int值添加到ArrayList
与List<T>
的代码会发生什么:
在“Mean”列中的运行时间差异为5x,突出显示为黄色。还要注意每个突出显示的差异(1000次运行中GC的数量),突出显示为红色。
使用分析器快速查看正在发生什么显示,大多数时间都花在进行GC而不是实际添加元素上。下面的棕色条代表阻塞垃圾收集器活动:
我已经编写了一份关于上述ArrayList
场景中发生的事情的详细分析。https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/。
类似的发现在Jeffrey Richter的“CLR通过C#”一书中。从第12章(泛型)开始:
[...] 当我在我的电脑上编译并运行此程序的发布版本(启用优化)时,我得到了下面的输出。 00:00:01.6246959 (GCs= 6) List<Int32>ArrayList
是不同类型数据的集合,而List<>
是相同类型依赖关系的集合。
如 .NET Framework文档 所述
我们不建议您在新开发中使用
ArrayList
类。相反,我们建议您使用通用的List<T>
类。ArrayList
类旨在保存异构对象集合。但是,它并不总是提供最佳性能。 我们建议采用以下方法:
- 对于异构对象集合,请使用
List<Object>
(在C#中)或List(Of Object)
(在Visual Basic中)类型。- 对于同构对象集合,请使用
List<T>
类。
另请参见 不应使用非泛型集合
ArrayList
不是类型安全的,而 List<T>
是类型安全的。简单明了 :)
ArrayList
和List<T>
之间的区别在于:
List<T>
, where T is value-type is faster than ArrayList
. This is
because List<T>
avoids boxing/unboxing (where T is value-type).ArrayList
used just for backward
compatibility. (is not a real difference, but i think it is
important note).ArrayList
then List<T>
ArrayList
has IsSynchronized
property. So, It is easy
to create and use syncronised ArrayList
. I didin't found IsSynchronized
property for List<T>
. Also Keep in mind this type of synchronization is relatively inefficient, 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
has ArrayList.SyncRoot
property which can be used for syncronisation (msdn). List<T>
hasn't SyncRoot
property, so in
the following construction you need to use some object if you use List<T>
:
ArrayList myCollection = new ArrayList();
lock(myCollection.SyncRoot) // ofcourse you can use another object for this goal
{
foreach (object item in myCollection)
{
// ...
}
}
List<>
的一般情况,而那个问题则专门询问了List<object>
。 - goodeye