Question

.NET IEnumerable what is it exactly?

I'm trying to understand what an IEnumerable<> is exactly.

I had thought it was just an interface saying the underlying data structure has these methods eg First() etc.

However I have tested the the code shown here in EF which I would have expected to produce a TOP query in the DB as if it were running as an IQueryable, but it instead causes it to pull the entire table in memory to perform its operation.

 IEnumerable<EntityObject> m = DbContext.GetDbSet<EntityObject>();
 var x = m.First();

So does treating something as an IEnumerable force it into operating as an array or list or something?

Note I do NOT need to know how to optimize the query to be more performant, I am trying to understand why simply treating it as a different interface and using the same methods results in different underlying logic happening.

 3  183  3
1 Jan 1970

Solution

 5

.Net IEnumerable what is it exactly?

As @ProgrammingLlama and @Henk Holterman already given you initial insight, However, I am trying expand a bit more.

As you may know IEnumerable is the base interface for all non-generic collections that can be enumerated, such as arrays, lists, or any other collection that implements IEnumerable. The main functionality provided by IEnumerable is the ability to iterate over a collection using a foreach loop.

So does treating something as an IEnumerable force it into operating as an array or list or something?

Actually, simply assigning an IQueryable<T> to an IEnumerable<T> does not immediately execute the query and load the data into memory. It's the subsequent operations, like calling First(), that force the execution of the query and loading of data into memory.

The key point is that while the assignment itself doesn't cause immediate execution, the operations performed on the IEnumerable afterward will be in-memory operations, and certain operations like First() will indeed execute the query and load data. Any subsequent operations for instance, Where, First, Select are performed in-memory.

Now back to your shared code snippet, to ensure that the First() operation is performed on the database rather than in-memory, you should keep the collection as IQueryable. This way, the First() method will be translated into a SQL query with a TOP 1 clause, and only the first entity will be fetched from the database.

So, you could modify your code as following:

IQueryable<EntityObject> m = DbContext.GetDbSet<EntityObject>();
var x = m.First();

Note: Please refer to this official document for additional example for

2024-07-03
Md Farid Uddin Kiron

Solution

 3

Had a bit of a decompiler dig into the methods. Far as I can tell the reason for the difference in functionality actually appears to be due to the fact that IEnumerables and IQueryables have different extension methods on them.

Looks like there is quite little going on in the interfaces themselves. This explains my initial misgivings as I couldn't understand how simply treating it as a different interface could effect the operations called on it.

The extension methods on the IQueryables cause it to execute the expressions it needs to query, whereas the Enumerable expressions prompt it to use GetEnumerator and move through them with MoveNext() which is what seems to trigger the query on the first call.

2024-07-03
F Dev