IEnumerable <t> vs T [] </t>

时间:2010-08-08 06:09:27

标签: c# arrays collections ienumerable

我只是意识到,在将T[]公开给我的观点而不是IEnumerable<T>时,我可能总是错了。

通常,对于这种代码:

foreach (var item in items) {}

item应为T[]IEnumerable<T>

如果我需要获取项目的计数,那么Array.Count会比IEnumerable<T>.Count()更快吗?

7 个答案:

答案 0 :(得分:31)

由于其他地方列出的原因,

IEnumerable<T>通常是更好的选择。但是,我想提出一点Count()。当他说类型本身实现Count()时,Quintin是不正确的。它实际上是在Enumerable.Count()中作为扩展方法实现的,这意味着其他类型不会覆盖它以提供更有效的实现。

默认情况下,Count()必须遍历整个序列以计算项目。但是,它 了解ICollection<T>ICollection,并针对这些情况进行了优化。 (在.NET 3.5 IIRC中,它仅针对ICollection<T>进行了优化。)现在数组实现了,因此Enumerable.Count()遵循ICollection<T>.Count并避免迭代整体序列。它仍然比直接调用Length稍慢,因为Count()必须发现它实现ICollection<T>开始 - 但至少它仍然是O(1)。

对于一般性能来说,同样的事情也是如此:当迭代数组而不是一般序列时,JITted代码可能会更紧凑。您基本上可以为JIT提供更多信息,甚至C#编译器本身也会以不同的方式处理数组(直接使用索引器)。

然而,这些性能差异对于大多数应用程序来说都是无关紧要的 - 我肯定会使用更通用的界面,直到我有充分的理由不这样做。

答案 1 :(得分:5)

这部分无关紧要,但标准理论将规定“针对接口的程序,而不是实现”。使用接口模型,只要符合相同的接口,就可以更改传递的实际数据类型,而不会影响调用者。

与此形成鲜明对比的是,您可能有理由专门公开数组,并且在这种情况下需要表达它。

对于您的示例,我认为IEnumerable<T>是可取的。还值得注意的是,出于测试目的,使用界面可以减少您在特定课程中所产生的头痛量,您必须一直重新创建,集合通常不是那么糟糕,但有接口合同你可以轻松地模拟是非常好的。

添加编辑:
这是无关紧要的,因为基础数据类型将实现Count()方法,对于应该访问已知长度的数组,我不担心方法的任何感知开销。 See Jon Skeet's answer有关Count()实施的解释。

答案 2 :(得分:3)

T [](一个大小,基于零)也使用ICollection<T>实现IList<T>IEnumerable<T>

因此,如果您希望在应用程序中使用较少的耦合IEnumerable<T>,则更可取。除非您想在 foreach 中进行索引访问。

答案 3 :(得分:2)

由于Array类实现了System.Collections.Generic.IList<T>System.Collections.Generic.ICollection<T>System.Collections.Generic.IEnumerable<T>通用接口,我将使用IEnumerable,除非您需要使用这些接口。

http://msdn.microsoft.com/en-us/library/system.array.aspx

答案 4 :(得分:1)

如果所有观点都关心或者应该关心的话,那么你的直觉就是正确的,这就是它的界面所需要的一切。

答案 5 :(得分:0)

从外部逻辑上(概念上)是什么?

如果是数组,则返回数组。如果唯一的一点是枚举,则返回IEnumerable。否则IList或ICollection可能就好了。

如果你想提供很多功能但不允许修改它,那么也许在内部使用List并返回从它的.AsReadOnly()方法返回的ReadonlyList。

答案 6 :(得分:0)

鉴于稍后将代码从数组更改为IEnumerable很容易,但是改变它的方式不是,我会使用IEnumerable,直到你知道你需要返回数组的小spead benfit。 / p>