Understanding IEnumerable and IQueryable in C#

Falafel Software Bloggers
Falafel Software
Published in
5 min readSep 5, 2014

--

A C-Sharp developer is always puzzled about usage of the following interfaces:

  • IEnumerable
  • IQueryable
  • ICollection
  • IList

I see developers are not that confident about usage of the mentioned interfaces. In this post, I am going to discuss basic differences among IEnumerable<T> and IQueryable<T> and in which scenario to use what.
IEnumerable<T>
The IEnumerable<T> is used to iterate a read only collection. It has only one method GetEnumeartor() which allows you to iterate the read only collection using a foreach loop. It only iterates in the forward direction. IEnumerable <T> is defined in as follows:

IEnumerable

As you see it does not contain any other functions like add, remove, count etc. So you cannot add, remove objects in IEnumerable collection. It is a read only collection and even to find the number of objects in collection, you need to iterate through entire collection. Some of the important points about IEnumerable<T> is as follows:

  • 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.

It is the base interface for any generic collection that can be enumerated using a foreach statement. To use iteration using a foreach the generic collection must implement the IEnumerable <T> and define GetEnumerator() method.
GetEnumerator() method is not thread safe. Enumerator reads collection by positioning itself at the first position of the collection. You need to call MoveNext() method to read next object in collection.
When to use IEnumerable<T>
Try answering the following questions,

  • Working with the read only collection
  • Need to read the objects in forward direction only
  • Not concerned about thread safety
  • Want to iterate the collection’s objects using foreach

If answer to any of the above questions are YES, then consider using IEnumerable <T>

IQueryable<T>

As of the MSDN documentation, the IQueryable<T> allows you to execute a query against a specific data source wherein type of data is not specified.
The IQueryable is defined as below:

IQueryable

It extends the IEnumerable, hence it allows you to iterate over collection using the foreach statement. All the properties of IQueryable are read only.
IQueryable<T> extends IQueryable and the IEnumerable. It is defined as follows:

iq3

If you are fetching records from remote databases IQueryable<T> should be used. It constructs the query using an Expression Tree. On the other hand in the IEnumerable <T> the query is constructed using delegates. Both IQueryable<T> and IEnumerable <T> support lazy loading of data from remote database servers.
When to use IEnumerable <T> or IQueryable<T>, let us view the generated SQL for the following LINQ:

DataClasses1DataContext context = new DataClasses1DataContext();
IEnumerable<Order> result = context.Orders;
var product = result.Where(x => x.OrderID == 10248);
context.Log = Console.Out;
foreach(var r in product)
{

Console.WriteLine(r.ShipName);
}

The generated SQL will be as follows:

IEnumerableSql

As you see even though we have applied filtering in query using where operator, IEnumerable<T> brings all data from database table and apply filter on returned data in memory.
On the other hand, let us rewrite above query using IQueryable<T> and examine the generated SQL query:

IQueryable<Order> result1 = context.Orders;
var product1 = result1.Where(x => x.OrderID == 10248);
context.Log = Console.Out;
foreach (var r in product1)
{
Console.WriteLine(r.ShipName);
}

Console.ReadKey(true);

The generated SQL will be as follows:

IQueryableSQL

As you notice, the generated SQL has where clause and LINQ to SQL will (provider in this case) bring only filtered data from database. If you use IQueryable with foreach then query will be evaluated and executed at the same time.
Some of the important points about IQueryable<T> are as follows:

  • It implements IEnumerable <T> 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

When you use IQueryable<T>, the query gets created using an Expression Tree. Further the LINQ provider converts the Expression tree into the real SQL query. Always remember that IQueryable<T> does only construct query and it loads data in deferred way.
When to use IQueryable<T>
Try answering the following questions,

  • Working with the queryable datasource
  • Need to apply filter on data at the datasource
  • Need to apply paging , composition
  • Working with external data source
  • Needs to load data in deferred way
  • Need to use foreach to iterate collection

If answer to all of the above questions are YES, then consider using IQueryable<T>

Be careful that your use of IQueryable does not break the encapsulation of your repository. You do not want data-specific concerns to leak from your repository abstraction into the rest of your code. If what you really want is the ability to use a repository but with custom filters, consider adding additional query methods or passing a specification or predicate to one of the repository’s List methods (which would still return IEnumerable).

Summary
The IEnumerable <T> works with collection in local memory whereas IQueryable<T> works with queryable data provider. If you are working with LINQ to SQL then best is to work IEnumerable <T> since you don’t work with live data and to add or remove call functions from DataConext class. IQueryable<T> does not return list of its own rather it constructs query. To return list from IQueryable<T> you need to use AsQueryable.

Originally published at Falafel Software Blog.

--

--