Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question
2  
there is also IList<T> as well –  jk. Nov 8 '11 at 13:50

3 Answers 3

up vote 16 down vote accepted

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.

share|improve this answer
    
First of all thanks. Now, the point of concern is how to decide which to use ??. Since List<T> implements both the interfaces, why not always use it in every place where IEnumerable or ICollection is required. Will always using list have a performance impact ? Please edit your answer to reply for these concerns –  Pankaj Upadhyay Nov 8 '11 at 7:48
    
I edited to answer your performance questions –  Jalayn Nov 8 '11 at 8:11
    
Thanks Jalayn.... –  Pankaj Upadhyay Nov 8 '11 at 12:27
    
+1, but I would add that in the rare cases where you actually need the to pass a list to a method, you should use IList rather than List in the method declaration. –  Konamiman Jul 25 '13 at 9:03
    
@Konamiman - Depends if you need List<> specific functionality, like .AddRange(). The IList<> doesn't expose that. –  Bobson Jul 25 '13 at 15:13

IQueryable:

query isn't executed until to really iterate over the items, maybe by doing a .ToList()

IEnumerable:

forward-only list of items. You can't get at "item 4" without passing items 0-3. read-only list, you can't add to it or remove from it. Still might use deferred execution.

IList:

random access to the full list entirely in memory supports adding and removing

ICollection:

Is between IEnumerable and IList. What is "best" depends on your requirements. Usually though an IEnumerable is "good enough" if you only want to display items. At least always use the generic variant.

share|improve this answer
    
this answer does not appear to add anything valuable over what has been already posted in earlier answers –  gnat Jul 25 '13 at 6:27
    
it's just a simple concept about all –  Zia Qammar Jul 25 '13 at 6:55

Have a look at the MSDN pages for ICollection and IEnumerable.

In very abstract terms, this is how I conceive of these types.

An IEnumerable is anything that can be enumerated - that is, iterated over. It doesn't necessarily mean a 'collection'; for example, an IQueryable implements IEnumerable and it's not a collection, but is something that can be queried to return objects. To implement IEnumerable an object only needs to be able to return an object when queried. I might say that I have an Enumerable of tasks that I'm going to do today (it's not a list because I haven't written it down or formulated it, but I could tell you what I'm going to do now, and if you asked 'and then?' I'd be able to tell you the following task).

An ICollection is more concrete than an IEnumerable. A key difference is that a Collection knows how many items it contains; to work out how many items are in an Enumerable you effectively loop through and count them:

Me: Guys, how many items do you each have in you?

Enumerable: I don't really know. Well, here's one item. I've got another one, so that's two. And another one, so that's three... and another one... ok so that's 2382. No more items, so I've got 2382. Don't ask me again because I'll have to go through them all again.

Collection: I've got 2382 items. I already know that.

A collection is typically something that already knows where all its elements are, and won't have to go and find or generate them when you ask for them. It's more... concrete than an Enumerable.

In my opinion the different between an Enumerable and a Collection is much larger than the difference between a Collection and a List. In fact I'm struggling to think of a practical difference between a Collection and a List, but I believe List provides better methods for searching and ordering.

Other types of Collection include Queue and Stack, as well as Dictionary.

The names of these types are quite useful - you can conceive of a queue and a stack as their real world counterparts, and consider the differences you might have to a List.

share|improve this answer
    
"I'm struggling to think of a practical difference between a Collection and a List" ... Later in your answer you answer this yourself. A List is an ICollection, but an ICollection isn't always a List (Queue, Stack, Dictionary, ...) –  Steven Jeuris Nov 8 '11 at 10:14
    
@Steven It's a very rambling answer. I agree that this is an important difference, but I wouldn't call it a practical difference. What does it mean to the user? –  Kirk Broadhurst Nov 8 '11 at 12:51
    
That's easy! :) Queue<int> queue = (Queue<int>)list; will throw an InvalidCastException when list is not a Queue<int>. The difference between queue and list is out of scope for this question. –  Steven Jeuris Nov 8 '11 at 12:54
    
Isn't the critical aspect of IEnumerable that it can return the current and next items - you sort of allude to that, but don't explicitly say so. Essentially something that implements IEnumerable alone can't return an arbitrary item of its members when queried - only the current one and the next one. –  cori Nov 15 '11 at 0:00
    
@cori That's a very succinct way of putting it, a lot clearer than my answer. –  Kirk Broadhurst Nov 15 '11 at 1:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.