I\'ve been working for the first time with the Entity Framework in .NET, and have been writing LINQ queries in order to get information from my model. I would like to progr
In general LINQ uses deferred execution. If you use methods like First()
and FirstOrDefault()
the query is executed immediately. When you do something like;
foreach(string s in MyObjects.Select(x => x.AStringProp))
The results are retrieved in a streaming manner, meaning one by one. Each time the iterator calls MoveNext
the projection is applied to the next object. If you were to have a Where
it would first apply the filter, then the projection.
If you do something like;
List<string> names = People.Select(x => x.Name).ToList();
foreach (string name in names)
Then I believe this is a wasteful operation. ToList()
will force the query to be executed, enumerating the People
list and applying the x => x.Name
projection. Afterwards you will enumerate the list again. So unless you have a good reason to have the data in a list (rather than IEnumerale) you're just wasting CPU cycles.
Generally speaking using a LINQ query on the collection you're enumerating with a foreach will not have worse performance than any other similar and practical options.
Also it's worth noting that people implementing LINQ providers are encouraged to make the common methods work as they do in the Microsoft provided providers but they're not required to. If I were to go write a LINQ to HTML or LINQ to My Proprietary Data Format provider there would be no guarantee that it behaves in this manner. Perhaps the nature of the data would make immediate execution the only practical option.
Also, final edit; if you're interested in this Jon Skeet's C# In Depth is very informative and a great read. My answer summarizes a few pages of the book (hopefully with reasonable accuracy) but if you want more details on how LINQ works under the covers, it's a good place to look.
Sometimes it might be a good idea to "cache" a LINQ query using ToList()
or ToArray()
, if the query is being accessed multiple times in your code.
But keep in mind that "caching" it still calls a foreach
in turn.
So the basic rule for me is:
foreach
(and thats it) - then I don't cache the queryforeach
and in some other places in the code - then I cache it in a var using ToList/ToArray