What's the difference between IEnumerable, IQueryable and List?

53

What is the difference between IEnumerable , IQueryable and List in .NET?

When is it better to use one or the other?

Why does ReSharper suggest changing the return of this function, for example, from List<T> :

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

for IEnumerable<T>

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

?

    
asked by anonymous 27.05.2014 / 18:50

3 answers

51

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 .

    
27.05.2014 / 19:08
31

IEnumerable , belongs to the System.Collections , and it exposes an enumerator, which supports an iteration over a simple non-generic collection (MSDN. IEnumerable Interface, Microsoft. 2014. Available in: link . Accessed on: 27.May.2014, translation). <T> is the basis for all collections that can be enumerated. The interfaces have a default method to implement the GetEnumerator .

By this illustration you realize the great importance of this Interface ( IEnumerable )

Figure 1 - "When to use IEnumerable, ICollection, IList and List" Source:ClaudioBernasconi'sTechBlog

IEnumerableeIEnumerable<T>representsalistofstronglytypedobjectsthatcanbeaccessedbytheindex.Providesmethodsforsearching,sorting,andmanipulatinglists.Thisclasshasseveralinterfacesthatimplementit:

  • IListandIList

  • ICollectionandICollection

  • IReadOnlyList

  • IReadOnlyCollection

  • IEnumerable

  • IEnumerable.(MSDN)ListclassListMicrosoft.2014.Availableat: link

That is, within List there are many features implemented from various interfaces. While the IEnumerable has behavior, the List implements such behavior, and also the compiler with IEnumerable postpones the work until its final execution, while the List forces the compiler to generate the data immediately. In the case of ReSharper, it does an optimization, and gives you the best framework for that method, since <T> is much simpler than IEnumerable<User> .

List<User> provides functionality to give values to queries in a specific data source in which 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 may be enumerated. (MSDN, IQueryable Interface, Microsoft, 2014. Available at: link . Accessed on: 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 enumerators.

References:

27.05.2014 / 21:33
23

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

Although it may seem, it does not necessarily only generate SQL commands: 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, that defines an object capable of relating other objects in sequence.

Not necessarily IEnumerable is a literal object. In cases where yield return is used (or rather, a generating function is used), what you get is an iterator that implements the interface. Calls to this iterator may 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 ordering or manipulation of the objects contained within the sequence, the language recommended is to use an object that implements ICollection ( which by the way also implements IEnumerable ).

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

For ReSharper , the suggestion occurs because IEnumerable is more generic and just supports return as a generating function, not a defined object ( yield return is the best way to illustrate that).

    
27.05.2014 / 19:06