This was an attempt to resume a very complex set of considerations. I agree that it may sound like the opposite.
Imagine that we have a function that returns a collection of items. This collection is internally created as an instance of
List<T>. If we want this output to be writeable, the function can return
ICollection<T>. If we want it to be read/only, the function can return
What I mean is that, given the restriction of being writeable or read-only, the interface with more functionalities should be returned. Ultimately the type itself. The functionalities are implemented anyway by the type and these don’t compromise the intent.
IReadOnlyList<T> , the client is free to enumerate the collection using
foreach, and can also use the
Count property. If
IEnumerable<T> was returned instead, only
foreach could be used and the collection has to be fully enumerated to get the number of items.
for is also much more performant than
is operator can be used to find if the collection implements these functionalities. This is done in several of the
System.Linq operations. I don’t like this approach because, it’s performed at runtime, taking a hit on performance, and the intent is not explicit. I wrote an article on this subject: https://firstname.lastname@example.org/enumeration-in-net-ii-9fd8e72cf83f
There may be an exception to these rules. When the function is private or internal, the type should be explicitly returned. Not an interface. This way, the performance of enumeration is much better as the enumerator is not boxed. This is not relevant for types that implement
IReadOnlyList<T> because the indexer can be used, but it’s very relevant for other collections.
I developed a Roslyn analyzer that can help you automatically find some of these patterns in your projects: https://github.com/NetFabric/NetFabric.Hyperlinq.Analyzer
The answer is long but I hope it does explain my sentence. Feedback is welcome…