Foreach in Select and List

1

I recently discovered that there is a big difference between doing some operations, such as Select and Where , in Queryable and enumerated objects, such as Enumerable and List . This and this question.

Knowing this, I was curious to know if there are differences between iterating values of a List and iterating values straight from a Select . I saw in the debug that when I only do Select I'm iterating over {System.Linq.Enumerable.WhereSelectListIterator<string, string>} .

When I do Where or Select in a list does the operation run the instant the method is called or only runs when I access the items or use ToList() ?

Also, is there any performance difference between the two cases?
Is it easier to iterate over a List or is it more costly to transform to List to later iterate?

Difference of this:

var lista = new List<string>() { ... };
var listaFiltrada = lista.Select(x => x).ToList();

foreach (var item in listaFiltrada) { ... }

For this:

var lista = new List<string>() { ... };
var selectFiltrado = lista.Select(x => x);

foreach (var item in selectFiltrado) { ... }
    
asked by anonymous 20.05.2016 / 21:17

1 answer

1
  

When I do Where or Select in a list, the operation is executed the instant the method is called or only executed when I access the items or use ToList() ?

Considering LINQ to SQL or Entity Framework, only at the moment of conversion to IEnumerable , that is, ToList() .

What Select does is to generate an iterator that will serve as a filter on the next operation, such as ToList() . In the case of IQueryable , this Select filter will be interpreted as the columns of a selection in SQL. For example:

var listaExemplo = context.Entidades.Select(x => new { x.Coluna1, x.Coluna2, x.Coluna3 }).ToList();

A SQL will be generated like this:

SELECT COLUNA1, COLUNA2, COLUNA3 FROM ENTIDADES

For objects in memory, Select returns this special object ( WhereSelectListIterator<string, string> ). It is an iterator, just like GetEnumerator also returns an iterator.

Here:

var listaFiltrada = lista.Select(x => x).ToList();

foreach (var item in listaFiltrada) { ... }

You solve the enumeration and pass to the foreach a materialized list, whereas here:

var selectFiltrado = lista.Select(x => x);

foreach (var item in selectFiltrado) { ... }

You indicate that selectFiltrado will be an enumerator (iterator) whose resolution will transform each enumeration object in the predicate from within Select (in the example, return the object itself without change). The list, therefore, does not materialize.

The first example is useful when:

  • You need to get something from the list as a list before foreach ;
  • You need to resolve a query SQL and only then manipulate the result.

The second example is useful when:

  • The list does not need to be materialized before foreach .
20.05.2016 / 21:27