What is the difference between Ienumerable, Iqueryable and List?

Asked

Viewed 24,262 times

63

What’s the difference between Ienumerable, Iqueryable and List no . NET?

When it’s best to use one or the other?

Why does Resharper suggest that I modify the return of that function, for example, List<T>:

private List<User> GetUsers(){ ... }

for IEnumerable<T>

private IEnumerable<User> GetUsers(){ ... }

?

  • Do you have an answer that has helped you? Is there anything I can change in my response to better suit your need?

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

3 answers

62


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.

39

IEnumerable, belongs to the namespace System.Collections, and exposes an enumerator, which supports an iteration on a simple non-generic collection (MSDN. Ienumerable, Microsoft interface. 2014. Available in: http://msdn.microsoft.com/pt-br/library/System.Collections.IEnumerable(v=vs.110). aspx. Accessed: 27.May.2014, translation) and
IEnumerable<T> belonging to the namespace System.Collections.Generic which exposes the enumerator, which supports a simple iteration over a collection of a specified type. (MSDN. Ienumerable interface<T>, Microsoft. 2014. Available in: http://msdn.microsoft.com/pt-br/library/9eekhta0(v=vs.110). aspx. Accessed: 27.May.2014, translation). The IEnumerable is the basis for all collections that can be enumerated. Interfaces have a default method to be implemented Getenumerator.

By this illustration you realize the great importance of this Interface (IEnumerable e IEnumerable<T>)

Figure 1 - "When to use Ienumerable, Icollection, Ilist and List" inserir a descrição da imagem aqui Source: Claudio Bernasconi’s Techblog

List represents a list of strongly typed objects that can be accessed by the index. Provides methods for searching, sorting and manipulating lists. This class has several interfaces that implement it:

That is, within List there are many implemented features of various interfaces. While Ienumerable has the behavior List implements such behavior, and also the compiler with Ienumerable postpones the work until its final execution, while List forces the compiler to generate the data immediately. In Resharper’s case, he does an optimization, and gives him the best working structure of that method, since the IEnumerable<User> is much simpler than the List<User>.

IQueryable provides the functionality to give values to queries in a specific data source where the data type is not specified. The Iqueryable interface inherits the Ienumerable interface so that if it represents a query, the results of that query can be listed. (MSDN. Iqueryable interface, Microsoft. 2014. Available at: http://msdn.microsoft.com/pt-br/library/system.linq.iqueryable(v=vs.110). aspx. Accessed: 27.May.2014, translation). As Ienumerable was said to be important for the three items reported in the question, it is the basis of the Numerators.

References:

  • 2

    Great answer. Very well referenced

26

IQueryable is a more specific interface that has a query provider, such as LINQ-To-SQL. It is a special object, that when using a method, it generates a query or a query structure for a database and returns these results as a list or a enumerable.

Although it seems, it doesn’t necessarily just generate commands SQL: depending on the data provider, you can generate any query through it, in theory. For example, Mongodb has its own provider that generates commands in its own format.

IEnumerable is an interface that implements objects with enumeration capability (IQueryable implements IEnumerable, inclusive), that is, defining an object capable of relating other objects in sequence.

Not necessarily IEnumerable is a literal object. In cases where it is used yield return (or rather, a generating function is used), what you get is an iterator that implements the interface. Calls to this iterator can return an element of the sequence or the whole sequence, depending on the method used.

A priori, an object that implements IEnumerable does not necessarily assume that it can be modified. For these cases, allowing sorting or manipulation of the objects contained within the sequence, what is recommended by the language is to use an object that implements ICollection (which also implements IEnumerable).

List<T> is the implementation of an interface object IEnumerable.

In the case of Resharper, the suggestion occurs because IEnumerable is more generic and rightly supports the return as a generating function, not a defined object (yield return is the best way to illustrate it).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.