IEnumerable <T> vs T []

sta*_*ker 21 c# arrays collections ienumerable

我只是意识到,也许我在揭露T[]我的观点时总是错了,而不是IEnumerable<T>.

通常,对于这种代码:

foreach (var item in items) {}
Run Code Online (Sandbox Code Playgroud)

item应该T[]还是IEnumerable<T>

而且,如果我需要得到物品的数量,那么Array.Count会更快IEnumerable<T>.Count()吗?

Jon*_*eet 31

IEnumerable<T>由于其他地方列出的原因,这里通常是更好的选择.但是,我想提出一点意见Count().当他说类型本身实现时,Quintin是不正确的Count().它实际上是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#编译器本身也会以不同的方式处理数组(直接使用索引器).

但是,对于大多数应用程序而言,这些性能差异将无关紧要- 在我有充分理由不这样做之前,我肯定会使用更通用的接口.


Qui*_*son 5

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

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

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

添加用于编辑:
这更无关紧要,因为底层数据类型将实现该Count()方法,对于应该访问已知长度的数组,我不担心该方法的任何感知开销. 有关Count()实施的解释,请参阅Jon Skeet的答案.

  • @stacker,你说的没错.如果您只想按连续顺序访问(不修改)元素,则"IEnumerable"是正确的选择.当您需要固定大小的集合以及通过索引访问和修改任何元素的能力时,数组是合适的 - [随机访问](http://en.wikipedia.org/wiki/Random_access). (2认同)