I see a lot of APIs that use custom collections instead of just using strongly-typed packaged generics.
For instance, the API will have a Object1Collection
instead of just a List<Object1>
(or whatever the appropriate generic would be).
When do you know to use one or the other? I understand you'd create a custom collection if you want to extend the capabilities of a pre-shipped generic collection, but what if that's not the case?
Is it prudent to create the custom collection from the beginning, with thoughts that in the future that object might scale up and require further capabilities, and it may be easier to just do that initially? Is that justification enough?
And if you just want to extend functionality, instead of define collection functionality, you would just derive your custom collection from a base generic collection class, otherwise inherit the interface accordingly? Is that typical?
3 Answers 3
In general, rarely if ever.
You'll occasionally make things that wrap collections and work on collections of things, but you will rarely make a class that is a generic, reusable collection. More often you'll have some class that represents some concept which uses a collection, rather than is a collection.
Why? Because frankly there's only so many data structures in the world, and they've pretty much all been implemented. Maybe you can come up with the next hash table, and if you do, then make a new collection type for it.
If you want to add functionality, either wrap the existing collection or add extension methods to it.
If you see a specific ObjectCollection
, I would assume that the API was made during .NET 1.0 (no generics) or for some API that has onerous interoperability requirements put in it.
Custom collections don't really make sense for general programming. Thats why List<T>
exists. But they sure make lots of sense in domain modelling. For example, you would like to have special behavior that happens when you add a new item into a collection. The best way to do it is to create custom collection class, derive from Collection<T>
and overload the Add
method.
Also, there is question of what actually is a "custom collection". Is having Add
method and implementing IEnumerable<T>
enough or does the class have to derive from Collection<T>
?
So as Telastyn said. You are generally not going to implement new collections in a way of creating new ways of storing data. That problem has long been solved. But you sure can (and should) create custom collections as a way of expressing domain behavior on those collections.
Here's what Microsoft says:
Collections (types that implement IEnumerable) are created mainly for two reasons: (1) to create a new data structure with structure-specific operations and often different performance characteristics than existing data structures (e.g., List, LinkedList, Stack), and (2) to create a specialized collection for holding a specific set of items (e.g., StringCollection). Data structures are most often used in the internal implementation of applications and libraries. Specialized collections are mainly to be exposed in APIs (as property and parameter types).
https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/guidelines-for-collections
This is what I gathered from the rest of the article:
For Return types, it's better to use custom collections for return types, especially for high level APIs. It allows better typing, readability, and extensibility. PLUS, and this is important, certain .NET implementations are not designed to be exposed through a public API. List and Dictionary are examples (more info in the article).
For defining Parameters:
DO use the least-specialized type possible as a parameter type. Most members taking collections as parameters use the IEnumerable interface.
Although the first paragraph in my response states that custom collections can be used as parameter types as well.
I know this is an old question, but I recommend that anyone with this question today read this article. It has a lot of goodies in it.
CustomCollection cc
look any cleaner thanList<myType> cc
?FooCollection
is lest I look up how it is implemented. If I see aList<Foo>
, I know straight away what it is. If allFooCollection
does is provide a "clean" alias for a well-known native .NET type, I say it's a bad move