In many projects I work on, whenever I have to return a read only collection, I use the IEnumerable<T>
interface and make it type specific like so:
Public ReadOnly Property GetValues() As IEnumerable(Of Integer) Get 'code to return the values' End Get End Property
Most of the time, I return a List but in some functions and read only properties I return an array which also serves the purpose alright by kind courtesy of Extension Methods.
My question is am I violating any design principles by returning IEnumerable<T>
s instead of specific types (e.g.: List<T>
, HashSet<T>
, Stack<T>
or Array
s)?
There's a received wisdom that it's always better to return the most specific interface – meaning the interface which has the smallest possible set of functions. By that token, since IEnumerable<T> is smaller than IList<T> you should return IEnumerable<T>.
IEnumerable is best to query data from in-memory collections like List, Array etc. IEnumerable doesn't support add or remove items from the list. Using IEnumerable we can find out the no of elements in the collection after iterating the collection. IEnumerable supports deferred execution.
ToArray might do an additional allocation and copy operation such that the buffer will be sized exactly to the number of elements. In order to confirm this the following benchmark is used. The results confirm that ToList is in most cases 10% - 15% faster.
One important difference between IEnumerable and List (besides one being an interface and the other being a concrete class) is that IEnumerable is read-only and List is not. So if you need the ability to make permanent changes of any kind to your collection (add & remove), you'll need List.
I generally prefer IEnumerable<T>
as well. The main thing is to ask yourself what actual (even minimum) functionality is being returned from the method (or passed to it, in the case of a method argument).
If all you need to do is enumerate over a result set, then IEnumerable<T>
does exactly that. No more, no less. This leaves you the flexibility to return more specific types in certain cases if need be without breaking the footprint of the method.
David's answer pretty much covers it; IEnumerable<T>
is best practice in general. You can see this by looking at most of the newer framework methods.
I just wanted to add that, since you specified read-only collection in your original question, you can enforce this by calling .ToList().AsReadOnly()
on your IEnumerable<T>
instance before returning it. This will create a concrete instance of ReadOnlyCollection<T>
for you to return. Your return type should still be IEnumerable<T>
, since the caller doesn't need to know that you are specifically returning a ReadOnlyCollection<T>
, but in this way you prevent the caller from shooting himself in the foot.
(Without this step, the caller could e.g. attempt to cast the IEnumerable<T>
it gets from your method to List<T>
. If the cast succeeds, which it will if that's what you were originally working with, the caller can then modify the same list you are operating on inside your method, with possibly unanticipated consequences.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With