tags:

views:

1727

answers:

12

When I'm writing my DAL or other code that returns a set of items, should I always make my return statement:

public IEnumerable<FooBar> GetRecentItems()

or

public IList<FooBar> GetRecentItems()

Currently, in my code I have been trying to use IEnumerable as much as possible but I'm not sure if this is best practice? It seemed right because I was returning the most generic datatype while still being descriptive of what it does, but perhaps this isn't correct to do.

+1  A: 

I think you can use either, but each has a use. Basically List is IEnumerable but you have count functionality, Add element, remove element

IEnumerable is not efficient for counting elements, or getting a specific element in the collection.

List is a collection which is ideally suited to finding specific elements, easy to add elements, or remove them.

Generally I try to use List where possible as this gives me more flexibility.

Use List getRecentItems() rather than IList GetRecentItems()

Stuart
+3  A: 

List<T> offers the calling code many more features, such as modifying the returned object and access by index. So the question boils down to: in your application's specific use case, do you WANT to support such uses (presumably by returning a freshly constructed collection!), for the caller's convenience -- or do you want speed for the simple case when all the caller needs is to loop through the collection and you can safely return a reference to a real underlying collection without fearing this will get it erroneously changed, etc?

Only you can answer this question, and only by understanding well what your callers will want to do with the return value, and how important performance is here (how big are the collections you would be copying, how likely is this to be a bottleneck, etc).

Alex Martelli
"safely return a reference to a real underlying collection without fearing this will get it erroneously changed" - Even if you return IEnumerable<T>, couldn't they simply cast it back to a List<T> and change it?
Kobi
Not every IEnumarable<T> is also a List<T>. If the object returned is not of a type that inherits from List<T> or implements IList<T> this would result in a InvalidCastException.
lowglider
List<T> has the problem that it locks you in to a particular implementation Collection<T> or ReadOnlyCollection<T> are preferred
Sam Saffron
A: 

It's not so simple when you are talking about return values instead of input parameters. When it's an input parameter, you know exactly what you need to do. So, if you need to be able to iterate over the collection, you take an IEnumberable whereas if you need to add or remove, you take an IList.

In the case of a return value, it's tougher. What does your caller expect? If you return an IEnumerable, then he will not know a priori that he can make an IList out of it. But, if you return an IList, he will know that he can iterate over it. So, you have to take into account what your caller is going to do with the data. The functionality that your caller needs/expects is what should govern when making the decision on what to return.

JP Alioto
+2  A: 

That depends...

Returning the least derived type (IEnumerable) will leave you the most leeway to change the underlying implementation down the track.

Returning a more derived type (IList) provides the users of your API with more operations on the result.

I would always suggest returning the least derived type that has all the operations your users are going to need... so basically, you first have to deremine what operations on the result make sense in the context of the API you are defining.

jerryjvl
+10  A: 

It really depends on why you are using that specific interface.

For example, IList<T> has several methods that aren't present in IEnumerable<T>:

  • IndexOf(T item)
  • Insert(int index, T item)
  • RemoveAt(int index)

and Properties:

  • T this[int index] { get; set; }

If you need these methods in any way, then by all means return IList<T>.

Also, if the method that consumes your IEnumerable<T> result is expecting an IList<T>, it will save the CLR from considering any conversions required, thus optimizing the compiled code.

Jon Limjap
@Jon FDG recommend using Collection<T> or ReadOnlyCollection<T> as a return value for collection types see my answer.
Sam Saffron
A: 

as all have said it depends, if you don't want Add/Remove functioanlity at calling layer then i will vote for IEnumerable as it provides only iteration and basic functionality which in design prespective i like. Returning IList my votes are always againist it but it's mainly what you like and what not. in performance terms i think they are more of same.

Usman Masood
A: 

One thing to consider is that if you're using a deferred-execution LINQ statement to generate your IEnumerable<T>, calling .ToList() before you return from your method means that your items may be iterated twice - once to create the List, and once when the caller loops through, filters, or transforms your return value. When practical, I like to avoid converting the results of LINQ-to-Objects to a concrete List or Dictionary until I have to. If my caller needs a List, that's a single easy method call away - I don't need to make that decision for them, and that makes my code slightly more efficient in the cases where the caller is just doing a foreach.

Joel Mueller
@Joel Mueller, I usually would call ToList() on them anyway. I generally don't like exposing IQueryable to the rest of my projects.
KingNestor
I was referring more to LINQ-to-Objects, where IQueryable doesn't generally enter the picture. When a database is involved, ToList() becomes more necessary, because otherwise you risk closing your connection before iterating, which doesn't work very well. However, when that isn't an issue, it's pretty easy to expose IQueryable as an IEnumerable without forcing an extra iteration when you want to hide the IQueryable.
Joel Mueller
+1  A: 

I think you can use either, but each has a use. Basically List is IEnumerable but you have > count functionality, Add element, remove element

IEnumerable is not efficient for counting elements

If the collection is intended to be readonly, or the modification of the collection is controlled by the Parent then returning an IList just for Count is not a good idea.

In Linq, there is a Count() extension method on IEnumerable which inside the CLR will shortcut to .Count if the underlying type is of IList, so performance difference is negliable.

Generally I feel (opinion) it is better practice to return IEnumerable where possible, if you need to do additions then add these methods to the parent class, otherwise the consumer is then managing the collection within Model which violates the principles, e.g. manufacturer.Models.Add(model) violates law of demeter. Of course these are just guidelines and not hard and fast rules, but until you have full grasps of applicability, following blindly is better than not following at all.

public interface IManufacturer { IEnumerable Models {get;} void AddModel(Model model); }

(Note if using nNHibernate you might need to map to private IList using different accessors)

mattcodes
A: 

If you do not counting in your external code it is always better to return IEnumerable, because later you can change your implementation (without external code impact), for example, for yield iterator logic and conserve memory resources (very good language feature by the way).

However if you need items count, don't forget that there is another layer between IEnumerable and IList - ICollection.

arbiter
A: 

I might be a bit off here, seeing that no one else suggested it so far, but why don't you return an (I)Collection<T>?

From what I remember, Collection<T> was the preferred return type over List<T> because it abstracts away the implementation. They all implement IEnumerable, but that sounds to me a bit too low-level for the job.

Tiberiu Ana
+6  A: 

Framework design guidelines recommend using the class Collection when you need to return a collection that is modifiable by by the caller or ReadOnlyCollection for read only collections.

The reason this is preferred to a simple IList is that IList does not inform the caller if its read only or not.

If you return an IEnumerable<T> instead, certain operations may be a little trickier for the caller to perform. Also you no longer will give the caller the flexibility to modify the collection, something that you may or may not want.

Keep in mind that LINQ contains a few tricks up its sleeve and will optimize certain calls based on the type they are performed on. So, for example, if you perform a Count and the underlying collection is a List it will NOT walk through all the elements.

Personally, for an ORM I would probably stick with Collection<T> as my return value.

Sam Saffron
A: 

In general, you should require the most generic and return the most specific thing that you can. So if you have a method that takes a parameter, and you only really need what's available in IEnumerable, then that should be your parameter type. If your method could return either an IList or an IEnumerable, prefer returning IList. This ensures that it is usable by the widest range of consumers.

Be loose in what you require, and explicit in what you provide.

Mel