Deferred Query Execution


When the query expression is defined during runtime, the query does not run. The query runs when the items are iterated.

Let’s have a look once more at the extension method Where(). This extension method makes use of the yield return statement to return the elements where the predicate is true. Because the yield return statement is used, the compiler creates an enumerator and returns the items as soon as they are accessed from the enumeration.

 public static IEnumerable<T> Where<T>(this IEnumerable<T> source,                                       Func<T, bool> predicate) {    foreach (T item in source)       if (predicate(item))          yield return item; }

This has a very interesting and important effect. With the example a collection of String elements is created and filled with the name arr. Next, a query is defined to get all names from the collection where the item starts with the letter J. The collection should also be sorted. The iteration does not happen when the query is defined. Instead, the iteration happens with the foreach statement, where all items are iterated. Just one element of the collection fulfills requirements of the where expression by starting with the letter J: Juan. After the iteration is done and Juan written to the console, four new names are added to the collection. Then the iteration is done once more.

  List<string> arr = new List<string>       { "Nino", "Alberto", "Juan", "Mike", "Phil" }; var query = from n in arr    where n.StartsWith("J")    orderby n    select n; Console.WriteLine("First iteration"); foreach (string name in query) {    Console.WriteLine(name); } Console.WriteLine(); arr.Add("John"); arr.Add("Jim"); arr.Add("Jack"); arr.Add("Denny"); Console.WriteLine("Second iteration"); foreach (string name in query) {    Console.WriteLine(name); } 

Because the iteration does not happen when the query is defined, but it does happen with every foreach, changes can be seen, as the output from the application demonstrates:

 First iteration Juan Second iteration Jack Jim John Juan

Of course, you also must be aware that the extension methods are invoked every time the query is used within an iteration. Most of the time this is very practical, as you detect changes in the source data. However, there are situations where this is impractical. You can change this behavior by invoking the extension methods ToArray(), ToEnumerable(), ToList(), and the like. In the example, you can see that ToList iterates through the collection immediately and returns a collection implementing IList<string>. The returned list is then iterated through twice, while in between the data source gets new names.

 List<string> arr = new List<string>       { "Nino", "Alberto", "Juan", "Mike", "Phil" }; IList<string> list = (from n in arr          where n.StartsWith("J")          orderby n          select n).ToList(); Console.WriteLine("First iteration"); foreach (string name in list) {    Console.WriteLine(name); } Console.WriteLine(); arr.Add("John"); arr.Add("Jim"); arr.Add("Jack"); arr.Add("Denny"); Console.WriteLine("Second iteration"); foreach (string name in list) {    Console.WriteLine(name); }

In the result, you can see that in between the iterations the output stays the same:

 First iteration Juan Second iteration Juan




Professional C# 2005 with .NET 3.0
Professional C# 2005 with .NET 3.0
ISBN: 470124725
EAN: N/A
Year: 2007
Pages: 427

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net