C# Generics – Differences Between Collection Generic Interfaces

cgenericsinterfaces

I have been playing around with C# for Windows and ASP.net MVC development for some time now. But I am still unclear on a few areas. I am trying to understand the basic difference between and performance issues with using and interchanging similar kinds of Generic Collection Interfaces.

What is the basic difference between IEnumerable<T>, ICollection<T>, List<T>(Class)?

I seem to use and interchange them without seeing any problem in my applications. Also, are there any more similar generic collections like these that can be interchanged with those three?

Best Answer

List<T> is a class and implements both the ICollection<T> and IEnumerable<T> interfaces. Also, ICollection<T> extends the IEnumerable<T> interface. They are not interchangeable, at least not from all points of view.

If you have a List<T>, you are guaranteed that this object implements methods and properties required to be implemented by the ICollection<T> and IEnumerable<T> interface. The compiler knows it and you are allowed to cast them "down" to either an ICollection<T> or an IEnumerable<T> implicitly. However, if you have an ICollection<T> you have to check explicitly in your code first whether it is a List<T> or something else, perhaps a Dictionary<T> (where T is a KeyValuePair) before casting it to what you desire.

You know that ICollection extends IEnumerable, so you can cast it down to an IEnumerable. But if you only have an IEnumerable, again you are not guaranteed that it is a List. It may be, but it could be something else. You should expect an invalid cast exception if you do attempt to cast a List<T> to a Dictionary<T> for example.

So they are not "interchangeable".

Also, there are a lot of generic interfaces, check out what you can find in the System.Collections.Generic namespace.

Edit: regarding your comment, there is absolutely no performance penalty if you use List<T> or one of the interfaces it implements. You will still need to create a new object, check out the following code:

List<T> list = new List<T>();
ICollection<T> myColl = list;
IEnumerable<T> myEnum = list;

list, myColl, and myEnum all point to the same object. Whether you declare it as a List or an ICollection or an IEnumerable I'm still requiring the program to create a List. I could have wrote this:

ICollection<T> myColl = new List<T>();

myColl, at runtime is still a List.

However, an this is the most important point... to reduce coupling and increase maintainability you should always declare your variables and method parameters using the lowest possible denominator possible for you, whether it is an interface or an abstract or concrete class.

Imagine that the only thing the "PerformOperation" method needs is to enumerate elements, do some work and exit, in that case you do not need the hundred more methods available in List<T>, you only need what is available in IEnumerable<T>, so the following should apply:

public void PerformOperation(IEnumerable<T> myEnumeration) { ... }

By doing that, you and other developers know that any object of a class implementing the IEnumerable<T> interface may be given to this method. It may be a List, a Dictionary, or a custom collection class another developer has wrote.

If on the contrary you specify you explicitly need a concrete List<T> (and although it is rarely the case in real life, it may still happen), you and other developers know that it must either be a List or another concrete class inheriting from List.