Resharper’s suggestion occurs because it’s usually better you deal with interfaces than concrete types, or otherwise analyzing a more generic type than a more specific one.
The fact of generating a List<T>
doesn’t mean you don’t have an object that’s not a IEnumerable<T>
, after all List<T>
is derived from IEnumerable<T>
. A list is a collection that allows its members to be enumerated, that is, you go analyzing element by element. A method GetEnumerator()
is used to obtain the enumerator (a kind of counter to sweep the elements). And a method MoveNext()
(of IEnumerator
) makes you advance to the next element.
Any object IEnumerable<T>
allows each element to be processed individually for each required operation instead of processing all elements of the collection in each separate operation, which would even prevent certain operations from being performed.
A IEnumerable<T>
is usually good for process elements that are already in memory. You can use it in a database query, but you will have to bring all the database results to memory to then process it.
When you wear one .ToList()
, is converting the result to a list. You do not give an example of usage, but believe by the question that you received a result that a IQueryable<T>
which is specific to LINQ. A IQueryable<T>
is also derived from a IEnumerable<T>
and admits Lazy loading allowing a better optimization of a query. That is, only the elements really needed for a certain operation are returned in the query for future analysis.
The use of IQueryable<T>
allows the construction of query expression trees. It is usually more suitable for use with database (LINQ To SQL for example) and other remote sources, especially when you need results pagination. These expressions can be obtained and executed with the methods IQueryProvider.CreateQuery()
and IQueryProvider.Execute()
.
A result IQueryable<T>
can be converted to a List<T>
but is usually converted to a IEnumerable<T>
to give more flexibility in subsequent operations.
See for example using a IEnumerable<T>
:
var ent = new EntFuncionarios();
IEnumerable<Funcionario> funcionario = ent.Funcionarios;
IEnumerable<Funcionario> temp = funcionario.Where(x => x.FuncID == 2).ToList<Funcionario>();
All employees will come from the database and then be analyzed one by one on Where
.
And with IQueryable<T>
:
var ent = new EntFuncionarios();
IQueryable<Funcionario> funcionario = ent.Funcionarios;
IEnumerable<Funcionario> temp = funcionario.Where(x => x.FuncID == 2).ToList<Funcionario>();
A SQL query is created and only the necessary data is brought to analyze this query.
The way the data filter works is the big difference. In the second case a query is generated and only when using the .ToList<Funcionario>
is that the result of this query is materialized in memory. You generate a query and not a final result. This filtered result can then be analyzed in more detail.
This materialization requires the query to be effectively executed. Like the IEnumerable<Funcionario>
and the IQueryable<Funcionario>
are evaluated late (Lazy Evaluation or deferred Execution), that is, it is evaluated on demand, according to need, you only get a real list when you generate that demand and this is effect with the conversion to a list with .ToList<Funcionario>
.
I put in the Github for future reference.
Do you have an answer that has helped you? Is there anything I can change in my response to better suit your need?
– Maniero
Yes, actually all the answers are very good and helped me. But reading the answers I have arisen some doubts that I will take when I find a time.
– Andre Figueiredo