Collection<T> Versus List<T> What Should You Use on Your Interfaces

Collection T versus List T what should you use on your interfaces?

To answer the "why" part of the question as to why not List<T>, The reasons are future-proofing and API simplicity.

Future-proofing

List<T> is not designed to be easily extensible by subclassing it; it is designed to be fast for internal implementations. You'll notice the methods on it are not virtual and so cannot be overridden, and there are no hooks into its Add/Insert/Remove operations.

This means that if you need to alter the behavior of the collection in the future (e.g. to reject null objects that people try to add, or to perform additional work when this happens such as updating your class state) then you need to change the type of collection you return to one you can subclass, which will be a breaking interface change (of course changing the semantics of things like not allowing null may also be an interface change, but things like updating your internal class state would not be).

So by returning either a class that can be easily subclassed such as Collection<T> or an interface such as IList<T>, ICollection<T> or IEnumerable<T> you can change your internal implementation to be a different collection type to meet your needs, without breaking the code of consumers because it can still be returned as the type they are expecting.

API Simplicity

List<T> contains a lot of useful operations such as BinarySearch, Sort and so on. However if this is a collection you are exposing then it is likely that you control the semantics of the list, and not the consumers. So while your class internally may need these operations it is very unlikely that consumers of your class would want to (or even should) call them.

As such, by offering a simpler collection class or interface, you reduce the number of members that users of your API see, and make it easier for them to use.

What is the difference between List (of T) and Collection(of T)?

Collection<T> is a customizable wrapper around IList<T>. While IList<T> is not sealed, it doesn't provide any customization points. Collection<T>'s methods are by default delegated to the standard IList<T> methods, but can be easily overridden to do what you want. It is also possible to wireup events inside a Collection<T> that I don't believe could be done with an IList.

In short, it's much easier to extend it after the fact, which could potentially mean a lot less refactoring.

Collection vs List which I have to use

There appear to be no docs for this, but Entity Framework supports any IEnumerable<T> for collection navigation properties.

So you can just declare them as:

  • IEnumerable<T>
  • ICollection<T>
  • Collection<T>
  • HashSet<T>
  • IList<T>
  • List<T>

And probably more. As far as Entity Framework is concerned, there's no difference, it'll assign the appropriate one at runtime and can do all it does with each one, apart from calling AddRange() on most of them, but when do you want to use that?

If you want databinding, you could use an ObservableCollection<T>, for example, otherwise I'd go with the leanest interface that still allows adding items: ICollection<T>.

When should I use the interface List instead of Collection

When you need the below benefits:

In addition to the operations inherited from Collection, the List interface includes operations for the following:

Listed as

Positional access — manipulates elements based on their numerical position in the list

Search — searches for a specified object in the list and returns its numerical position

Iteration — extends Iterator semantics to take advantage of the list's sequential nature

Range-view — performs arbitrary range operations on the list.

C#: Difference between List T and Collection T (CA1002, Do not expose generic lists)

In short, the generic list does not have virtual methods for Add, Remove etc, as it was designed to be fast, not extensible. This means that you cannot swap this concrete implementation out for a useful subclass (even though you can subclass it as it is not sealed).

Therefore, by exposing the List itself, you can never extend your collection to track add or remove operations (for example) without breaking the public contract of the class.

By exposing your collection as an IList or some-such, you can still use the List as the actual backing-store, but you retain future extensibility as you can swap out the concerete implementation later without changing the public contract of your class.

List or Collection: which one to use in interfaces?

A good API should provide all that is needed without exposing unnecessary implementation details.

I find myself using List or Set the most. Trying to replace List or Set with Collection sometimes makes the API awkward to use without really offering any added decoupling or abstraction.

I try to avoid Maps in method signatures because I think it is a telltale sign that the input/output is too complex. This can be solved by creating a specific wrapper class for this data or by changing the method's location so it has direct access to the data (e.g. putting it in the class that you were passing to the method).

Don't forget your object oriented design is there to make life easier for those maintaining and calling your code, not to achieve some holy grail of perfection. There are usually several sensible ways to model a problem and which one you choose depends on your own style and the expected future complexities/use cases of the code base you are working on.

List T is better then ICollection T ? And why implement redundant interfaces?

Q1:

A List<T> might be more 'powerfull' than an ICollection<T>, but it is less abstract.
If ICollection<T> exposes everything you need, then why would you specify that he has to use a List<T> and thereby limit the user of your interface / method / whatever and constrain him that he has to use a List<T>?

The user of your class / interface might not use a List<T> but a HashedSet<T> for instance, which is also an ICollection<T>, but not a List<T>.

If he wants to pass his HashedSet to your method, that would mean he has to convert his set to a list, if you define that your method should accept a List instead of an ICollection<T>.

An ICollection is less specific than a List, which means that as soon as a type implements ICollection, that type can be consumed by your method.
Offcourse you can only do this when an ICollection specifies all the functionality that you need in your method.

If you need to be able to access a certain element in the collection by using an indexer, an ICollection<T> would not be a good choice as an argument type for your interface, since ICollection<T> does not define such an indexer.

Q2 & Q3:

It's all about abstraction and the Liskov substitution principle.

When you have a method which accepts an IEnumerable for instance, you can assign an IReadonlyCollection to it, because it implements IEnumerable next to IEnumerable<T>. If it would only implement IEnumerable<T>, then you would not be able to use assign an IReadOnlyCollection<T> as an argument to a method which accepts an argument of type IEnumerable.

Is it better to use List or Collection?

It just depends, do you want your users to be able to index into the data? If yes, use List. Both are interfaces, so you're not leaking implementation details, really, you just need to decide the minimum functionality needed.

Should we use ICollection T in the Interface and Collection T in the class?

If you can expose an interface rather than a class, expose the interface; expose the class only if you must do so, for example, to expose methods not available on the interface. You should do it both in your interface and in your class.

The rationale is that information hiding is a "good thing", so if you can do it without losing of generality, you should do so.



Related Topics



Leave a reply



Submit