I ended up in this post while searching for solutions to my problem - which led me to propose a new answer there - and - to be confronted with the following question:
Considering ICollection
implements IEnumerable
, and all linq extensions apply to both interfaces, is there any scenario where I would benefit from working with an IEnumerable
instead of an ICollection
?
The non generic IEnumerable
, for instance, does not provide a Count
extension.
Both ICollection
interfaces do.
Given all ICollection
, in any case, provide all functionality IEnumerable
implement - since it itself implements it - why then would I opt for IEnumerable
in place of ICollection
?
Backward compatibility with previous frameworks where ICollection
was not available ?
I think there are actually two questions to answer here.
When would I want IEnumerable<T>
?
Unlike other collection types and the language in general, queries on IEnumerable
s are executed using lazy evaluation. That means you can potentially perform several related queries in only enumeration.
It's worth noting that lazy evaluation doesn't interact nicely with side effects because multiple enumeration could then give different results, you need to keep this in mind when using it. In a language like C#, lazy evaluation can be a very powerful tool but also a source of unexplained behaviour if you aren't careful.
When would I not want ICollection<T>
?
ICollection<T>
is a mutable interface, it exposes, amongst other things, add and remove methods. Unless you want external things to be mutating your object's contents, you don't want to be returning it. Likewise, you generally don't want to be passing it in as an argument for the same reason.
If you do want explicit mutability of the collection, by all means use ICollection<T>
.
Additionally, unlike IEnumerable<T>
or IReadOnlyCollection<T>
, ICollection<T>
is not covariant which reduces the flexibility of the type in certain use cases.
Non-generic versions
Things change a bit when it comes to the non-generic versions of these interfaces. In this case, the only real difference between the two is the lazy evaluation offered by IEnumerable
and the eager evaluation of ICollection
.
I personally would tend to avoid the non-generic versions due to the lack of type safety and poor performance from boxing/unboxing in the case of value types.
Summary
If you want lazy evaluation, use IEnumerable<T>
. For eager evaluation and immutability use IReadOnlyCollection<T>
. For explicit mutability use ICollection<T>.