[ACCEPTED]-IEnumerable<T> vs T[]-ienumerable

Accepted answer
Score: 33

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

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

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

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

Score: 7

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

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

For your example I 9 think IEnumerable<T> would be desirable. It's also worthy 8 to note that for testing purposes using 7 an interface could reduce the amount of 6 headache you would incur if you had particular 5 classes you would have to re-create all 4 the time, collections aren't as bad generally, but 3 having an interface contract you can mock 2 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 1 an explanation of the Count() implementation.

Score: 3

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

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

Score: 3

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


Score: 1

Your gut feeling is correct, if all the 3 view cares about, or should care about, is 2 having an enumerable, that's all it should 1 demand in its interfaces.

Score: 0

What is it logically (conceptually) from 8 the outside?

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

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

Score: 0

Given that changing the code from an array 5 to IEnumerable at a later date is easy, but 4 changing it the other way is not, I would 3 go with a IEnumerable until you know you 2 need the small spead benfit of return an 1 array.

More Related questions