Collections in C# are very commonly used and probably each developer uses them intensively every day at work. Different collections provide different capabilities and you should be familiar with how they work to do your job efficiently. In this article, I will explain the difference between IEnumerable
, ICollection
, IList
, and IQueryable
in C#, which are fundamental interfaces when working with collections. Each of these interfaces describes a collection suitable for different contexts.
IEnumerable
IEnumerable is the base interface in C# when it comes to collections. It is the root, and most of the collections extend its functionality by deriving from it, including ICollection, IList, and IQueryable:
IEnumerable provides really basic functionality. Such collections can only be iterated through. You canโt add, remove, update or even count the items. It gives us only one method GetEnumerator, which returns the IEnumerator object. This object knows how to iterate over a collection. It keeps the current element and has a method MoveNext to get to the next element.
ICollection
This interface derives from IEnumerable, which gives it iteration ability and extends this functionality. Here come additional operations like add, remove, clear, and contains. There is also a CopyTo method, which can transform an ICollection into an Array.
IList
IList derives from ICollection and gets all its functionalities, including the IEnumerable as well. The IList has index and you can get items by index, get index of an item, insert and remove at specific index.
IQueryable
IEnumerable, ICollection, and IList are collections working with data in memory. They are creating LINQ-to-objects queries. IQueryable on the other side is used for working with collections in external data sources like databases for example. It creates LINQ-To-SQL queries. The in-memory collections use delegates to process the data (filter, sort, etc.), while the IQuerable is working with an expression tree. When you pass a code to the LINQ query of an IQuerable, it is runtime converted to an expression tree, which will be understood by the SQL. This provides us with the powerful feature of filtering the data, directly in the database.
For instance:
The IEnumerable will get all music albums from the database, and then it will apply the filter in memory, to result in only โRapโ genres.
On the other hand, the code passed to the Where clause of the IQuerable will be transformed into an expression tree, which will be executed in the database. So, the filtering will be executed there, and only โRapโ albums will be returned to the server.
In conclusion the IQuerable has IQueryProvider, which knows how to work with a specific data source. In our example, the IQuerable has IQueryProvider for SQL.
Conclusion
Here is a graphic representation the different collectionsโ capabilities: