在C#中何时使用ArrayList而不是array[]?

39

我经常使用ArrayList而不是“普通”的array[]

当我使用ArrayList时,我感到好像在作弊(或懒惰),那么什么情况下可以使用ArrayList替换数组?


9
那并不是欺骗,而是让生活更轻松。尽可能让生活变得更轻松。 - Michał Piaskowski
11个回答

66

数组是强类型的,并且作为参数很有效。如果您知道您的集合长度固定,应该使用数组。

ArrayList 不是强类型的,每次插入或检索都需要转换回原始类型。如果您需要一个方法来获取特定类型的列表,ArrayList 将会有所不足,因为您可以传递包含任何类型的 ArrayList。ArrayList 在内部使用动态扩展数组,因此当其达到容量时,还需要扩展内部数组的大小。

您真正想使用的是一个泛型列表,比如 List<T>。它具有数组和 ArrayList 的所有优点。它是强类型的,并支持可变长度的项目。


6
ArrayList不使用LinkedList作为其内部数据结构,而是使用向量(Vector)。向量是一个数组,在添加/插入/删除操作时会动态调整大小。 - Alex
很好,你发现了这个错误。我很久没查过了。我已经更正了答案。 - Bob

14

除了Bob和Frederick的回答,我想指出的是,虽然数组具有协变性,但泛型列表没有。例如,类型为MyChildClass[]的数组可以轻松地转换为MyParentClass[],而List<MyChildClass>不能直接转换为List<MyParentClass>

如果你需要协变性,可以使用数组、使用LINQ的Cast()方法或其他方式逐个转换每个项或等待C# 4


1
C# 4不会为列表提供协变性 - 只提供IEnumerable<T>(和一些委托) - 它要求严格的“in” 异或 “out”用法,并且List<T>既有“in”和“out”用法。 - Marc Gravell

7
这里还有一个关于变异的想法;数组 (T[]) 是完全可变的,无法受到保护。 List<T> 没有提供任何有用的扩展点,但像 Collection<T> (或许多其他 IList<T> 实现) 这样的东西允许您添加代码,例如在添加项目之前检查它们;同样,您可以拥有只读的 IList<T> 实现,在需要不可变性的线程安全性方面非常有用。
我倾向于在内部方法逻辑中使用数组(可能作为局部变量),作为 params 参数,或者在我知道项目长度并且我知道代码选择不对其进行变异(作为私有字段)的一些高度优化的情况下使用它们。除此之外,List<T> 等更常见,因为在添加/删除项目时它们具有更少的开销。

6
除非代码的那一部分绝对需要高性能,否则使用ArrayList是完全可以的。

2
在1.1版本中,你应该通常使用List<T>,而在2.0版本中则是更好的选择。 - Marc Gravell

4
更好的做法是,无论在哪里使用 ArrayList,都应该使用 List<T> 泛型集合。它比前者更加强类型化。

1

我从Java的角度回答这个问题,但基本问题是相同的。使用更高级的抽象不应该让你感到内疚。毕竟,你使用的是String而不是char[]或者byte[]?我甚至建议在可能的情况下再往前走一步,使用List接口。唯一需要降低一步的原因是出于性能考虑。

使用更高级的集合抽象有很多优点。你可以添加装饰器使List只读、固定大小、检查进入或离开集合的项目或使用视图(参见C#中的GetRange和Java中的subList)。

顺便说一句,ArrayList应该总是基于一个原始数组,否则名称就是错误的。操作通常实现得就像你使用原始数组时所期望的那样。如果使用了链表,通常会命名为LinkedList。这也是使用接口的优点之一:您可以随后更改所使用的实现。

使用集合的一些问题使得它们变得笨重。其中一个警告是,集合通常基于对象,并且语言在原始类型和对象类型之间存在相当大的差距。有限的泛型也没有太大帮助。尽管如此,除非有充分的理由,否则我建议使用集合而不是数组。

对于原始值,您还可以考虑使用原始集合库,例如GNU Trove。不知道C#是否有类似的东西。


1

0
如果您需要一个原始类型的数组,请使用Array以获得更好的性能,因为它将避免自动装箱和拆箱。但前提是您事先知道所需的大小。

0

首先,如果您只打算处理特定类型,那么不应该使用ArrayList。例如,如果您只期望一个字节数组,则应该仅接受一个字节数组。

我认为唯一需要考虑使用ArrayList的情况是代替List。


0
数组的大小是静态的,因此如果您在设计时知道大小,请使用数组。它应该更快,但我自己没有测试过。如果您需要频繁更改对象的计数(从集合中添加或删除对象),请使用ArrayList或更好的.NET 2通用列表。它也更容易使用,因此如果性能不是关键,您可以始终使用List。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接