LINQ & IEnumerable<String> Re-evaluation
Good morning,
I wrote the following LINQ query
public static Func<String, IEnumerable<String>> ListaCorreccoes = (StrPalavra) =>
{
return (from StrTmp in ListaPossiveisCorreccoes(StrPalavra)
from StrTmp2 in ListaPossiveisCorreccoes(StrTmp)
where PalavraConhecida(StrTmp2)
select StrTmp2).Distinct();
};
which, to my surprise, is much faster than using two foreach
cicles. After running this function using ListaTmp = ListaCorreccoes("comutador");
, where ListaTmp
is of type IEnumerable<String>
, I need to print ListaTmp
's cardinality using
Console.Write(">> Prima qualquer tecla para listar todas as " + ListaTmp.Count() + " correcções...");
and to print the contents of ListaTmp
, using
foreach (String StrTmp in ListaTmp)
Console.WriteLine(StrTmp);
However, both the last and prior-to-last lines of code cause ListaTmp and thus the query to be re-evaluated, which is so very strange since the var开发者_Python百科iable is being assigned the result of the query. Why has this code such a strange behaviour?
Thank you very much.
That's because LINQ uses deferred execution. See Charlie Calvert's article on LINQ and Deferred Execution.
Try this instead:
var ListaTmp = ListaCorreccoes("comutador").ToList();
This enumerates once and stores the result in a List<string>
.
You might find Jon Skeet's articles useful:
- Iterators, iterator blocks and data pipelines
- Iterator block implementation details: auto-generated state machines
This is because ListaTmp is not a result set, but a query. Specifically for the Count, you're actually creating a new query (you expend the Linq expression) which you then execute.
The real type of ListaTmp is not IEnumerable, but IQueryable, which is a Linq query.
精彩评论