C#中ArrayList
和List<>
之间有什么区别?
只有List<>
有类型,而ArrayList
不是吗?
答案 0 :(得分:481)
是的,差不多。 List<T>
是一个通用类。它支持存储特定类型的值,而无需转换到object
或从T
转换(当ArrayList
是ArrayList
情况下object
是值类型时,会产生装箱/拆箱开销。 List<T>
只存储IEnumerable<T>
个引用。作为通用集合,Cast
实现了通用OfType
接口,可以在LINQ中轻松使用(无需任何ArrayList
或List<T>
调用)。
ArrayList
属于C#没有泛型的日子。它被弃用,而不是{{1}}。您不应在以.NET&gt; = 2.0为目标的新代码中使用{{1}},除非您必须与使用它的旧API进行交互。
答案 1 :(得分:94)
使用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
答案 2 :(得分:23)
添加到以上几点。在64位操作系统中使用ArrayList
占用的内存比在32位操作系统中使用的内存大2倍。同时,通用列表List<T>
将使用比ArrayList
低得多的内存。
例如,如果我们在32位中使用19MB的ArrayList
,则在64位中需要39MB。但是如果32位的通用列表List<int>
为8MB,那么64位只需要8.1MB,与ArrayList相比,差异为481%。
来源:ArrayList’s vs. generic List for primitive types and 64-bits
答案 3 :(得分:18)
要添加的另一个区别是线程同步。
ArrayList
通过Synchronized属性提供一些线程安全性,该属性返回集合周围的线程安全包装器。包装器通过在每次添加或删除操作时锁定整个集合来工作。因此,尝试访问集合的每个线程必须等待轮到一个锁。这不可扩展,并且可能导致大型集合的性能显着下降。
List<T>
不提供任何线程同步;用户代码必须在多个线程上同时添加或删除项目时提供所有同步。
此处有更多信息{{3}}
答案 4 :(得分:6)
简单回答是,
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/
答案 5 :(得分:3)
ArrayList
是不同类型数据的集合,而List<>
是其自身类型的相似类型的集合。
答案 6 :(得分:3)
ArrayList
不是类型安全的,而List<T>
是类型安全的。简单:))。
答案 7 :(得分:1)
我认为ArrayList
和List<T>
之间的差异是:
List<T>
,其中T是值类型比ArrayList
快。这是
因为List<T>
避免装箱/拆箱(其中T是值型)。ArrayList
仅用于落后
兼容性。 (这不是真正的区别,但我认为是
重要提示)。ArrayList
然后List<T>
ArrayList
拥有IsSynchronized
属性。所以,很容易
创建和使用同步ArrayList
。我找不到IsSynchronized
的{{1}}属性。另外请记住,这种类型的同步效率相对较低,msdn):
List<T>
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
属性,可用于同步(msdn)。 ArrayList.SyncRoot
没有List<T>
属性,所以
如果使用SyncRoot
:
List<T>
答案 8 :(得分:0)
如.NET Framework documentation
中所述我们不建议您将
ArrayList
类用于新 发展。相反,我们建议您使用通用的List<T>
类。ArrayList
类旨在容纳异构对象 对象的集合。但是,它并不总是提供最好的 性能。相反,我们建议以下内容:
- 对于异构对象集合,请使用
List<Object>
(在C#中)或List(Of Object)
(在Visual Basic中)类型。- 对于同类对象,请使用
List<T>
类。
答案 9 :(得分:0)
性能已经在几个答案中作为区别因素提到了,但是要解决“ ArrayList
慢多少?”和“ 为什么整体速度慢” ?”,请在下面看看。
每当将值类型用作元素时,ArrayList
的性能都会急剧下降。考虑简单添加元素的情况。由于装箱正在进行-ArrayList
的“添加”仅接受object
个参数-垃圾收集器被触发执行比List<T>
还要多的工作。
时差是多少?至少比List<T>
慢几倍。只需看一看将1000万个int值添加到ArrayList
与List<T>
的代码中会发生什么:
在“平均值”列中,运行时间差异为 5倍,以黄色突出显示。另请注意,每个垃圾收集完成的数量之间的差异以红色突出显示(GC数量/ 1000次运行)。
使用探查器快速查看发生的情况表明,大部分时间都花在了GC上,而不是实际添加元素。下面的棕色条表示阻止垃圾收集器的活动:
我在https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/上详细分析了上述ArrayList
场景的情况。
类似的发现在Jeffrey Richter的“通过C#进行CLR”中。从第12章(泛型)开始:
[…]当我编译并运行发布版本时(已启用优化 在我计算机上的该程序上,我得到以下输出。
00:00:01.6246959(GCs = 6)列表
00:00:10.8555008(GCs = 390)Int32的ArrayList
00:00:02.5427847(GCs = 4)列表
00:00:02.7944831(GCs = 7)字符串的ArrayList这里的输出显示 使用具有Int32类型的通用List算法的好处是 比在Int32中使用非通用ArrayList算法要快。在 实际上,差异是惊人的:1.6秒与将近11秒 秒。快了约7倍!!另外,使用值类型 (Int32)与ArrayList会导致发生很多装箱操作, 导致390个垃圾回收。同时,清单 该算法需要6个垃圾回收。
答案 10 :(得分:-2)
使用&#34; List&#34;你可以防止出现错误。避免运行时转换错误非常有用。
示例:
这里(使用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.
}
}
答案 11 :(得分:-3)
对我来说,了解你的数据。如果我继续在效率的基础上扩展我的代码,我将不得不选择List选项作为解密我的数据的方式,而不是总是想知道类型的不必要的步骤,尤其是“自定义类型”。如果机器了解差异并且可以确定我实际处理的是什么类型的数据,那么为什么我要阻止并且浪费时间通过“IF THEN ELSE”确定的回转?我的理念是让机器为我而不是我在机器上工作?了解不同目标代码命令的独特差异对于使代码有效有很大帮助。
汤姆约翰逊 (一次进入......一次退出)答案 12 :(得分:-6)
这不仅仅是区别。 ArrayList成员可以像普通数组一样通过索引访问,并且ArrayList成员可以很容易地按直接和反向顺序排序,并且两个ArrayList可以很容易地合并,而简单List就不是这种情况。
了解更多信息http://www.cirvirlab.com/index.php/c-sharp-code-examples/112-c-sharp-arraylist-example.html