Best Type to set as return type for methods that return a collection?
Which is the best type to us for returning collections?
Should I use IList<T>
, IEnumerable&开发者_StackOverflow社区lt;T>
, IQueryable<T>
, something else? Which is best and why?
I'm trying to decide which I should use typically, both in the interface and the implementation of a few classes that I'm writing.
edit Let me nail this down a little further, I am using LINQ to SQL to return data over a WCF Service. It feels like that may make a change in the best type to use?
The Framework Design Guidelines state:
Use
Collection<T>
or a subclass ofCollection<T>
for properties or return values representing read/write collections.public Collection<Session> Sessions { get; }
Use
ReadOnlyCollection<T>
, a subclass ofReadOnlyCollection<T>
, or in rare casesIEnumerable<T>
for properties or return values representing read-only collections.public ReadOnlyCollection<Session> Sessions { get; }
In general, prefer
ReadOnlyCollection<T>
.
Regarding LINQ, the guidelines, which were created for .NET 3.5, are clear but not (imo) entirely convincing in the justification:
The review body made an explicit decision that LINQ should not change this guideline ["Do not return
IEnumerator<T>
, except as the return type of aGetEnumerator
method"]. Your callers can end up with a clumsy object model if they choose not to use LINQ or a language that does not support it.
Use the least general Type that all possible return types will conform to. i.e, if the method you are looking at might return a List<int>
or an int[]
, then I'd type as IEnumerable<int>
... If it could return List<int>
or a List<Employee>
or an int[]
I'd type as IEnumerable
. If it always returned either a Collection<Employee>
or a Collection<SalariedEmployee>
then return Collection<Employee>
If the method will always generate the same type, use that type...
In a consuming method or interface, otoh, where the returned object is being used, you should use the opposite philosophy, Type the incoming method parameter as the least general type that is required by the internal functionality of the code in the consuming method... i.e, if all the method does with the collection object is enumerate through it using foreach
, then the incoming parameter type should IEnumerable<>
If the collection is unordered or doesn't need random access, IEnumerable is correct. If it's a list and you want to expose it as one, then declare the method or property to return IList, but you may well need to return a ReadOnlyCollection wrapper over that collection (either directly or using syntax such as List.AsReadOnly()). I would return IQueryable only if I had some useful overrides.
I default to IEnumerable. I'm shooting for the minimal interface to expose. Both IList<T>
and IQueryable<T>
implement IEnumerable<T>
. So unless you have other specific requirements for the methods I'd go for minimalism and use the least derived type. If you have other requirements in your calling code, such as performance of indexed lookups or getting the number of items in the collection then you might want to choose another type such as ICollection<T>
.
When writing applications, I don't see any problem with returning a specific generic type, e.g.:
List<myType> MyMethod()
{
...
}
In my experience, this is easy for the original developer, and easy for other developers to understand what the original developer intended.
But if you're developing some kind of framework that will be used by other developers, you might want to be more sophisticated - returning an interface, for example.
It ultimately depends on what you want to do with the data being returned. Remember that IEnumerable implies (by that I mean forces) you to access the data in a sequential manner. You can't add to it, alter it, and you can't access an item at a specific point in the array.
IList doesn't have this problem, but you have to provide additional functionality to implement it. If you inherit from a .net object, you might not have to worry about it, but it really depends on how you are creating the object.
Each have their trade offs and there is no one to always default to.
精彩评论