views:

320

answers:

7

I wish to return an ordered list of items from a method. Should my return type be IEnumerable or IList?

+1  A: 

IEnumerable is less specific than an IList, that is, IList has functions that IEnumerable does not.

Compare the two to see if one has functions you need that the other does not.

Charlie Salts
+2  A: 

If you want to return an ordered list maybe you should return a SortedList.

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

You can associate an order with the objects.

Ben Cawley
this looks like the answer....
Ben Aston
Can you point me at any information that tells me what .NET collections guarantee ordering?
Ben Aston
True, a sorted list hits by its type, that the result is sorted. but allows manipulation of it. if this is not intended, i would rather go with a ienumerable, and document the sorting in the description.
cRichter
This is useful if the client code will need information on the ordering key used. If not, IEnumerable is preferable in .NET 3.5 or higher (the LINQ extension methods allow all necessary read access, including O(1) Count and indexing.)
Dan Bryant
`Count()` and `ElementAt()` are only O(1) for a few special cases - in general they will enumerate the items in the sequence and therefore run in O(n).
Daniel Brückner
`SortedList<K,V>` is a Dictionary-type collection. There is noting in the OQ indicating that is what is needed.
Henk Holterman
OP said "ordered", not "sorted". Ordered means it maintains the original ordering. This is true of the majority of collections, and probably any collection that implements `IList<T>` since that has an indexer. Any collection that doesn't maintain ordering will say so in its documentation, like `Dictionary<TKey, TValue>.KeyCollection` or `HashSet<T>`.
Joe White
Well, ordering and sorting aren't exactly the same thing. Its possible to have a list that's ordered, but not sorted.
quanticle
+1  A: 

An IList has the methods for changing the items (like Add), maybe you want to select between ICollection and IEnumerable.

The ICollection extends IEnumerable and has the Count property available that can be useful.

munissor
+3  A: 

Its easy, if the caller should only use it Readonly, use IEnumerable. as this is then also supports covariance (result can be casted to a base type)

cRichter
It's covariant, actually, but great point.
Joe White
interesting point re covariance
Ben Aston
The IOrderedEnumerable<TElement> interface is returned by OrderBy Enumerable extension methods. Its readonly too.
Bear Monkey
@mjf. good point. IOrderedEnumerable would be the right one... never used it.
cRichter
+2  A: 

Generally, it's better to return IEnumerable<T>, as long as that has everything the caller needs.

IEnumerable<T> is foreachable, which is all that's needed for many consumers. It's also read-only, which is often a good thing -- it means you can sometimes optimize by returning your actual backing collection, without worrying too much about someone modifying it without telling you.

However, if the consumer needs methods that aren't on IEnumerable<T>, then IList<T> might make more sense. For example, the caller may want to call Contains, which isn't on IEnumerable<T>. Or the caller may want to index into the list, rather than iterating it from start to finish.

But you can do Contains and indexing on IEnumerable<T> too, via LINQ's Contains and ElementAt extension methods. So there's a question of degree here. If the caller only needs to ask one question that isn't available on IEnumerable<T>, like "is this empty", then return an IEnumerable<T> and use the Any extension method. But if the caller uses IList<T> operations extensively, return IList<T>.

Joe White
By using the LINQ versions of Contains and ElementAt, you maybe can run into performance problems, cause under the hood it just makes a foreach, so it will always be O(n). Depending on the implementation of IList Contains or ElementAt this can be a O(1) operation.
Oliver
@Oliver, you're wrong to say "always". The LINQ Contains and ElementAt first try casting the collection to `ICollection<T>` / `IList<T>` so they can call the O(1) method for you. The O(n) implementations are only used if that fails. If you're returning a `List<T>` typed as `IEnumerable<T>`, then Contains and ElementAt are still O(1), though with a bit of extra overhead. You can confirm this in Reflector.
Joe White
@Joe: Thanks for the information, there is still some new to learn. ;-)
Oliver
+8  A: 

There is a hierarchy here: interface IList<T> : IEnumerable<T>, ...;

You want to aim for the least possible coupling, so return an IEnumerable<T> if that is enough. It probably will be.

Return an IList<T> if the situation requires that the caller gets a List that it can use to Add/Insert/Remove. But even then, it might be better if the caller created his own List from the IEnumerable collection.

Henk Holterman
+2  A: 

It depends what you want to do with the result. If you need to get the count of items or get random access to individual items, go with an IList.

If callers just want to iterate through the items then go with IEnumerable - but you should document whether or not the returned value will be evaluated lazily or not - many IEnumerable instances these days represent queries that will be executed when the collection is enumerated. To be on the safe side, if what you are returning won't be evaluated on demand, I'd go with IList.

Alex Humphrey
+1 for emphasizing documentation.
wtfsven