简体   繁体   中英

IEnumerable<T> vs T[]

I just realize that maybe I was mistaken all the time in exposing T[] to my views, instead of IEnumerable<T> .

Usually, for this kind of code:

foreach (var item in items) {}

item should be T[] or IEnumerable<T> ?

Than, if I need to get the count of the items, would the Array.Count be faster over the IEnumerable<T>.Count() ?

IEnumerable<T> is generally a better choice here, for the reasons listed elsewhere. However, I want to bring up one point about Count() . Quintin is incorrect when he says that the type itself implements Count() . It's actually implemented in Enumerable.Count() as an extension method, which means other types don't get to override it to provide more efficient implementations.

By default, Count() has to iterate over the whole sequence to count the items. However, it does know about ICollection<T> and ICollection , and is optimised for those cases. (In .NET 3.5 IIRC it's only optimised for ICollection<T> .) Now the array does implement that, so Enumerable.Count() defers to ICollection<T>.Count and avoids iterating over the whole sequence. It's still going to be slightly slower than calling Length directly, because Count() has to discover that it implements ICollection<T> to start with - but at least it's still O(1).

The same kind of thing is true for performance in general: the JITted code may well be somewhat tighter when iterating over an array rather than a general sequence. You'd basically be giving the JIT more information to play with, and even the C# compiler itself treats arrays differently for iteration (using the indexer directly).

However, these performance differences are going to be inconsequential for most applications - I'd definitely go with the more general interface until I had good reason not to.

It's partially inconsequential, but standard theory would dictate "Program against an interface, not an implementation". With the interface model you can change the actual datatype being passed without effecting the caller as long as it conforms to the same interface.

The contrast to that is that you might have a reason for exposing an array specifically and in which case would want to express that.

For your example I think IEnumerable<T> would be desirable. It's also worthy to note that for testing purposes using an interface could reduce the amount of headache you would incur if you had particular classes you would have to re-create all the time, collections aren't as bad generally, but having an interface contract you can mock easily is very nice.

Added for edit:
This is more inconsequential because the underlying datatype is what will implement the Count() method, for an array it should access the known length, I would not worry about any perceived overhead of the method. See Jon Skeet's answer for an explanation of the Count() implementation.

T[] (one sized, zero based) also implements ICollection<T> and IList<T> with IEnumerable<T> .

Therefore if you want lesser coupling in your application IEnumerable<T> is preferable. Unless you want indexed access inside foreach .

Since Array class implements the System.Collections.Generic.IList<T> , System.Collections.Generic.ICollection<T> , and System.Collections.Generic.IEnumerable<T> generic interfaces, I would use IEnumerable, unless you need to use these interfaces.

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

你的直觉是正确的,如果所有的观点都关心或者应该关心的是具有可枚举的,那就是它在界面中应该要求的全部。

What is it logically (conceptually) from the outside?

If it's an array, then return the array. If the only point is to enumerate, then return IEnumerable. Otherwise IList or ICollection may be the way to go.

If you want to offer lots of functionality but not allow it to be modified, then perhaps use a List internally and return the ReadonlyList returned from it's .AsReadOnly() method.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM