数组与列表<T>:何时使用哪个?

MyClass[] array; List<MyClass> list; 

当一个人比另一个人更可取时,情况是什么? 为什么?

实际上,你很less想要使用一个数组。 当你想添加/删除数据时,绝对使用List<T> ,因为调整数组的大小很昂贵。 如果您知道数据是固定长度的,并且您希望针对一些非常特定的原因(基准testing后)进行微优化,则数组可能会有用。

List<T>比数组提供了更多的function(尽pipeLINQ使它稍微有点),并且几乎总是正确的select。 当然,除了params论证之外。 ;-p

作为一个反面的List<T>是一维的; 因为你有像int[,]string[,,]这样的矩形(等)数组int[,]但是在对象模型中还有其他的方式来模拟这种数据(如果你需要的话)。

也可以看看:

  • 如何/何时放弃在c#.net中使用数组?
  • 数组,有什么意义?

也就是说,我在protobuf-net项目中使用了很多数组, 完全是为了performance:

  • 它做了大量的位移,所以byte[]对于编码来说非常重要。
  • 我使用本地滚动byte[]缓冲区,我填充之前发送到底层的stream(和vv); 比BufferedStream等快;
  • 它内部使用一个基于数组的对象模型( Foo[]而不是List<Foo> ),因为大小一旦build成就被修复,并且需要非常快速。

但这绝对是一个例外; 对于一般的业务线处理, List<T>每次都赢。

真的只是回答添加一个我很惊讶的链接还没有被提及:埃里克的Lippert的博客条目“数组被认为有些有害”。

你可以从标题中判断,它是build议在任何实际的地方使用集合,但正如马克指出的那样,有很多地方只有数组才是真正的解决scheme。

在处理数据时使用数组:

  • 规模固定,或不太可能增长
  • 适当地大(根据algorithm,超过10,50,100个元素)
  • 你会做很多的索引,即你知道你会经常需要第三个元素,或者第五个,或者其他什么。

使用以下列表:

  • 可变长度数据列表
  • 主要用作堆栈或队列,或者需要整体迭代
  • 当你不想编写一个expression式来获取声明的最终数组大小,你不想浪费大量的select

使用hashmap:

  • 可变长度数据列表
  • 需要像数组索引

实际上,几乎所有的时候你都需要一个列表或hashmap。 下一次你select一个数据结构,考虑一下为你做什么(或者你的代码)。 然后根据这个select一些东西。 如果有疑问,尽可能select一些一般的东西,即一个接口,你可以很容易地replace实现。 其他答案中的一些好链接也是如此。

尽pipe其他答案build议List<T> ,您将要处理时使用数组:

  • 图像位图数据
  • 其他低级数据结构(即networking协议)

除非你真的关心性能,那么我的意思是,“你为什么使用.Net而不是C ++?” 你应该坚持List <>。 维护和更轻松地完成所有为您调整幕后arrays的肮脏工作。 (如果需要的话,List <>对于select数组大小非常聪明,所以通常不需要)。

如果集合本身的不变性是客户端和提供者代码之间的契约的一部分(不一定是集合内的项目的不变性),并且IEnumerable不适合时, 优先使用数组。

例如,

 var str = "This is a string"; var strChars = str.ToCharArray(); // returns array 

很显然,对“strChars”的修改不会改变原来的“str”对象,而不pipe“str”的基础types的实现级别的知识。

但是,假设

 var str = "This is a string"; var strChars = str.ToCharList(); // returns List<char> strChars.Insert(0, 'X'); 

在这种情况下,如果插入方法将会或不会改变原来的“str”对象,那么单独的代码片段就不清楚了。 它需要实现级别的String知识来做出决定,这违反了Design by Contract方法。 在string的情况下,这不是什么大不了的事情,但几乎在所有其他情况下都可能是一个大问题。 将List设置为只读会有帮助,但会导致运行时错误,而不是编译时。

如果我确切地知道需要多less个元素,比如我需要5个元素和5个元素,那么我使用一个数组。 否则,我只是使用一个List <T>。

大多数情况下,使用List就足够了。 一个List使用一个内部数组来处理它的数据,当向List添加比当前容量更多的元素时会自动调整数组的大小,这使得它比一个需要事先知道容量的数组更容易使用。

请参阅http://msdn.microsoft.com/en-us/library/ms379570(v=vs.80).aspx#datastructures20_1_topic5以获取有关C#中的列表的更多信息,或仅反编译System.Collections.Generic.List<T>

如果您需要多维数据(例如使用matrix或graphics编程),则可能需要使用array

一如既往,如果记忆或performance是一个问题,那就衡量它! 否则,你可能会对代码做出错误的假设。

还没有提到的另一种情况是,当一个项目的数量很多时,每个项目都由一组固定的相关但独立的variables组成(例如一个点的坐标或者一个三angular形的顶点)。 一个暴露的字段结构数组将允许其元素有效地“修改” – 这是任何其他集合types不可能的。 因为结构数组在RAM中连续保存其元素,所以对数组元素的顺序访问可能非常快。 在代码需要依次遍历一个数组的情况下,一个结构数组可以比2:1的因子优于数组或其他类对象引用。 此外,更新元素的能力可以允许一系列结构胜过任何其他types的结构集合。

虽然数组不能resize,但是要让代码存储数组引用以及正在使用的元素的数量并不难,并且根据需要将数组replace为更大的数组。 或者,我们可以很容易地为类似List<T>的types编写代码,但暴露了它的后台存储,从而允许我们说MyPoints.Add(nextPoint);MyPoints.Items[23].X += 5; 。 请注意,如果代码尝试访问超出列表的末尾,则后者不一定会引发exception,但是在用法上概念上与List<T>非常相似。

它完全依赖于需要数据结构的上下文。 例如,如果您正在创build要由其他function或服务使用的项目,则使用List是完美的方法。

现在,如果你有一个项目列表,你只是想显示它们,说网页上的数组是你需要使用的容器。

我认为最实用的答案是“这些差异可能对于你所需要完成的东西并不重要,特别是因为它们都实现了IEnumerable ,所以按照stream行的约定和用法一个List直到你有一个理由不,在这一点上,你可能会有你的理由使用List的数组。

大多数情况下,在托pipe代码中,您希望集合尽可能容易地工作,而不必担心微观优化。

.NET中的列表是数组的封装,并在内部使用数组。 列表上操作的时间复杂度与数组相同,但是所有附加的function/列表的易用性(如自动resize和列表类的方法)会带来更多的开销。 非常多,我会build议在所有情况下使用列表,除非有一个令人信服的理由这样做,例如,如果您需要编写极其优化的代码,或正在与其他代码围绕数组构build。