views:

132

answers:

4

Somebody told me this but i have not seen this anywhere and i have used it all over, i don't see why would it be bad practice.

Example of what i mean is having functions such as:

public List<SomeCustomeType> GetListOfStuff()
{
}

or

public void DoSomeStuff(List<SomeCustomeType> param)
{

}

can anyone tell me why would this be bad practice or should not be used? thanks!

A: 

No, it's not bad. It might be better to use the generic interface IList<T> than the generic class List<T>, though.

erikkallen
Why not just return an IEnumerable or ICollection?
the_drow
Returning a ReadOnlyCollection<T> is even better.
Developer Art
@the_drow: Because member's consumer maybe will need to use `List<T>` or `IList<T>` specific members. By the same reason don't return `object`
abatishchev
@drow: Sure, you could do that, too. For the parameter, that choice could be quite simple: If you need indexing, take a list; if you need the count, take a collection; otherwise an enumerable will do. For the return value, it's trickier, though, since you need to guess whether the caller is likely to need indexing and/or count.
erikkallen
@Developer Art: Only if returned collection must be read-only..
abatishchev
@erikkallen: well, now with LINQ extensions it's not strictly necessary to return List to have Count or Indexing, because LINQ wraps them for you on IEnumerable. This would let you to change for example from list to array in the future, without changing the method signature. But of course if you need to modify the collection you can't return IEnumerable...
digEmAll
@digEmAll: Yes, but indexing an IEnumerable is O(n), but a list is O(1). Of course, Linq will use the IList implementation if available, but your caller cannot rely on it.
erikkallen
@erikkallen: yes about caller confidence you're right. Anyway, you could specify it (i.e. ElementAt is O(1)) in the documentation...
digEmAll
@digEmAll: Yes, and in case you have a ... IList<T>.
erikkallen
@erikkallen: of course, but with IList you have also Add/Remove methods, even if you don't want to expose them.
digEmAll
If you don't want the caller to Add/Remove things, return a `ReadOnlyCollection`. Just casting the list to an IEnumerable doesn't help, since the caller can just cast it back and do the Add/Remove.
erikkallen
A: 

the first is better by far. it is clear that the method creates new list and return it, it is unclear who is responsible to create the second version list and what will happen if it is not empty...

tsinik
+5  A: 

Closed and Open generic types can be and are used in the framework and should be used. If you are using an incorrect type or exposing functionality you don't need, then it might be bad practice - for example, it is better to return IList<T> then List<T> as then you are not tied to the implementation and can use any type that implements IList<T>.

In a similar vein, you should only use types that expose the minumun required - better to return IEnumerable<T> than IList<T> if you only ever need to enumerate over the returned list.

Oded
yeah this is my understanding as well, I want to see if there is anyone in the other camp of though. thanks.
codewrath
+2  A: 

In the era of LINQ and its associated extension methods, it's considered best practice to return IEnumerable<T>, even if the underlying collection implements IList<T>. The LINQ extension methods Count() and ElementAt() both have optimizations when the underlying collection is an IList<T>, so the performance impact is generally negligible.

This practice insulates the client code from the details of how you're managing the collection (maybe you'll want to use a different type of collection in the future?) The main thing to consider when following this pattern is to clearly document if you're doing some form of stateful lazy evaluation that may warrant the client caching the result on their own (using ToArray(), for instance.)

Dan Bryant