MyClass[] array;
List<MyClass> list;
什么情况下应该选择其中一个?为什么?
MyClass[] array;
List<MyClass> list;
什么情况下应该选择其中一个?为什么?
实际上很少需要使用数组,任何时候想要添加/删除数据都应该使用 List<T>
,因为调整数组大小是昂贵的。如果您知道数据长度固定,并且您想要针对某些非常特定的原因进行微观优化(经过基准测试),那么数组可能有用。
List<T>
比数组提供了更多功能(尽管 LINQ 差不多),几乎总是正确的选择。当然,除了 params 参数之外。 ;-p
作为对比 - List<T>
是一维的;而你可以有诸如 int[,]
或 string[,,]
等矩形(等)数组 - 但在对象模型中还有其他建模此类数据的方式(如果需要)。
另请参见:
话虽如此,我在我的protobuf-net项目中大量使用数组;完全是为了性能:
byte[]
几乎是必需的;byte[]
缓冲区,在发送到底层流之前填充该缓冲区(反之亦然);比使用 BufferedStream
等更快;Foo[]
而不是 List<Foo>
),因为一旦构建完成大小就固定了,并且需要非常快。但这确实是一个例外;对于一般的业务处理,List<T>
每次都赢过其他数据结构。
我只是回答并添加一个链接,我很惊讶这个链接还没有被提到:Eric Lippert的博客文章"数组被认为有点危险。"
从标题可以判断出它建议在实际情况下尽可能使用集合 - 但正如Marc所指出的那样,有很多地方数组确实是唯一可行的解决方案。
除了其他推荐使用 List<T>
的答案之外,处理以下情况时您将需要使用数组:
List<T>
而不是字节数组有何不妥之处? - Konrad Rudolph除非你真的关心性能,我的意思是,“你为什么不用C++而使用.Net?”你应该坚持使用List<>。它更容易维护,并且可以在幕后为您调整数组大小。 (如果必要,List<> 在选择数组大小方面相当聪明,因此通常不需要您手动调整大小。)
当集合本身的不可变性是客户端和提供程序代码之间契约的一部分(不一定是集合内部项的不可变性),并且IEnumerable不适用时,应优先使用数组而不是List。
例如:
var str = "This is a string";
var strChars = str.ToCharArray(); // returns array
很明显,“strChars”的修改不会改变原始的“str”对象,无论“str”底层类型的实现级别知识如何。
但是假设
var str = "This is a string";
var strChars = str.ToCharList(); // returns List<char>
strChars.Insert(0, 'X');
在这种情况下,仅凭代码片段就不清楚insert方法是否会改变原始的"str"对象。需要String的实现级别知识才能做出判断,这违反了按合同设计的方法。在String的情况下,这并不是什么大问题,但在几乎所有其他情况下都可能成为一个大问题。将List设置为只读确实有所帮助,但会导致运行时错误而不是编译时错误。str
内部使用一个数组,而 ToCharArray
返回对该数组的引用,那么客户端可以通过更改该数组的元素来改变 str
,即使大小保持不变。然而,您写道“很明显修改“strChars”不会改变原始的“str”对象”。我在这里错过了什么?从我所看到的情况来看,无论是哪种类型,客户端都可以访问内部表示形式,并且这将允许某种形式的突变。 - Tim MB数组 vs. 列表是一个经典的可维护性 vs. 性能问题。几乎所有开发者都遵循的经验法则是,你应该追求两者,但当它们发生冲突时,选择可维护性而非性能。这个规则的例外是当性能已经被证明是一个问题时。如果将这个原则应用到数组 vs. 列表中,那么你会得到以下结论:
使用强类型列表,直到你遇到性能问题。如果你遇到性能问题,请决定是否放弃使用列表并转向使用数组,以使你的解决方案在性能方面获得更大的好处,而不会对其维护造成损害。
如果我知道我需要多少个元素,比如说我需要5个元素,而且永远只需要这5个元素,那么我会使用一个数组。否则,我会使用List<T>。
List
足以满足需求。 List
使用内部数组来处理其数据,并在向List
添加比其当前容量更多的元素时自动调整数组大小,相比数组更易于使用,因为您需要预先知道其容量。System.Collections.Generic.List<T>
。array
。对于方法参数声明,我倾向于使用IReadOnlyList<MyClass>
或IList<MyClass>
,这两者都可以接受数组和列表。例如:void Foo(IList<int> foo)
可以像这样调用:Foo(new[] { 1, 2, 3 })
或Foo(new List<int> { 1, 2, 3 })
。
MyClass[]
和List<MyClass>
都实现了IList<MyClass>
。List<MyClass>
作为参数但仅使用其功能子集的方法,则声明为IList<MyClass>
(或更严格的IReadOnlyList<MyClass>
)可能更方便调用者。List
,它只是实现了IList
接口。 - Rufus L