The IEnumerable
Some of the important points about IEnumerable
- It is a read only collection.
- It iterates only in forward direction.
- It does not support adding, removing objects on collection.
- It provides enumerator to iterate collection in forward direction.
If you are fetching records from remote databases IQueryable
Some of the important points about IQueryable
- It implements IEnumerable
so the results can be iterated using foreach - It is best suited to query against external data sources.
- It creates query using an Expression Tree
- It is used to query a queryable data source
IQueryable
:- query isn't executed until you really iterate over the items, maybe by doing a
.ToList()
or aforeach
- extends IEnumerable
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
- extends IEnumerable and ICollection
ICollection
:- Is between IEnumerable and IList.
- extends IEnumerable
Which type should you depend on?
Now that we have looked at all of the interfaces in question, we are ready to decide which interface we should depend on in which situation. Generally it’s a great idea to only depend upon things we really need. I am going to show you how this decision can be made very easily and what you can expect to gain if you do so.If you use a more narrow interface type such as IEnumerable instead of IList, you protect your code against breaking changes. If you use IEnumerable, the caller of you method can provide any object which implements the IEnumerable interface. These are nearly all collection types of the base class library and many custom defined types in addition. The caller code can be changed in the future and your code won’t break that easily as it would if you had used ICollection or even worse IList.
If you use a wider interface type such as IList, you are more in danger of breaking code changes. If someone wants to call your method with a custom defined object which only implements IEnumerable it simply won’t work and result in a compilation error.
Generally you should always use that type that provides a contract for only the methods you really use.
The following table gives you an overview of how you could decide which type you should depend on.
Interface | Scenario |
IEnumerable, IEnumerable |
The only thing you want is to iterate over the elements in a collection. You only need read-only access to that collection. |
ICollection, ICollection |
You want to modify the collection or you care about its size. |
IList, IList |
You want to modify the collection and you care about the ordering and / or positioning of the elements in the collection. |
List, List |
Since in object oriented design you want to depend on abstractions instead of implementations, you should never have a member of your own implementations with the concrete type List/List. |