Resharper's suggestion is because it's often better to deal with interfaces than concrete types, or by analyzing another way to use a more generic type than a more specific type.
Generating a List<T>
does not mean that you do not have an object other than 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. An GetEnumerator()
method is used to get the enumerator (a kind of counter to scan the elements). And a MoveNext()
method (from% IEnumerator
) does you move on to the next element.
Any object IEnumerable<T>
allows each element to be processed individually for each required operation rather than processing all elements of the collection in each separate operation, which would even prevent certain operations from being performed.
A IEnumerable<T>
is often good for processing elements that are already in memory . You can use it in a database query, but you will have to bring all the results from the database into memory and then process it.
When you use .ToList()
, you are converting the result to a list. You do not give an example usage, but I 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 better optimization of a query. That is, only the elements really needed for a given operation are returned in the query for further analysis.
Using IQueryable<T>
allows the construction of query expression trees. It is usually suitable for database use (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 IEnumerable<T>
to give more flexibility in subsequent operations.
See in example using 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 in 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 in for this query.
The way the data filter works is the big difference. In the second case a query is generated and only when using .ToList<Funcionario>
is the result of this query materialized in memory. You generate a query, not an end result. This filtered result can then be analyzed in more detail.
This materialization forces the query to be effectively executed. Since IEnumerable<Funcionario>
and IQueryable<Funcionario>
are belatedly evaluated ( lazy evaluation or deferred execution ), that is, it is evaluated on demand, according to the need, you only get a real list when you generate this demand and this is effect with the conversion to a list with% / p>
I placed it on GitHub for future reference .