Console.WriteLine("First execution");
Console.WriteLine("---------------");
foreach (int n in oddNums) Console.WriteLine(n);
//---add 20 to each number in the array---
for (int i = 0; i < 11; i++) nums[i] += 20;
Console.WriteLine("Second execution");
Console.WriteLine("----------------");
foreach (int n in oddNums) Console.WriteLine(n);
Console.ReadLine();
}
}
}
The program prints out the following output:
First execution
---------------
87
49
45
13
3
Second execution
107
69
65
33
23
Because the output for the second foreach
loop is different from the first, the program effectively proves that the query is not executed until it is accessed.
Deferred execution works regardless of whether you are using the query or method syntax.
Forced Immediate Query Execution
One way to force an immediate execution of the query is to explicitly convert the query result into a List
object. For example, the following query converts the result to a List
object:
var oddNums = nums.Where
(n => n % 2 == 1).OrderByDescending(n => n).ToList();
In this case, the query is executed immediately, as proven by the following program and its output: using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication5 {
class Program {
static void Main(string[] args) {
int[] nums = {
12, 34, 10, 3, 45, 6, 90, 22, 87, 49, 13, 32
};
var oddNums = nums.Where
(n => n % 2 == 1).OrderByDescending(n => n).ToList();
Console.WriteLine("First execution");
Console.WriteLine("---------------");
foreach (int n in oddNums) Console.WriteLine(n);
//---add 20 to each number in the array---
for (int i = 0; i < 11; i++) nums[i] += 20;
Console.WriteLine("Second execution");
Console.WriteLine("----------------");
foreach (int n in oddNums) Console.WriteLine(n);
Console.ReadLine();
}
}
}
Here's the program's output:
First execution
---------------
87
49
45
13
3
Second execution
87
49
45
13
3
The output of the first and second execution is the same, proving that the query is executed immediately after it's defined.
To force a LINQ query to execute immediately, you can use aggregate functions so that the query must iterate over the elements at once. An aggregate function takes a collection of values and returns a scalar value.
Aggregate functions are discussed in more detail later in this chapter.
Following is an example that uses the Count()
aggregate function. The program selects all the odd numbers from an array and then counts the total number of odd numbers. Each number is then multiplied by two (which makes them all become even numbers).
static void Main(string[] args) {
int[] nums = {
12, 34, 10, 3, 45, 6, 90, 22, 87, 49, 13, 32
};
var oddNumsCount = nums.Where
(n => n % 2 == 1).OrderByDescending(n => n).Count();
Console.WriteLine("First execution");
Console.WriteLine("---------------");
Console.WriteLine("Count: {0}", oddNumsCount);
//---add 20 to each number in the array---
for (int i = 0; i < 11; i++)
nums[i] *= 2; //---all number should now be even---
Console.WriteLine("Second execution");
Console.WriteLine("----------------");
Console.WriteLine("Count: {0}", oddNumsCount);
Console.ReadLine();
}
The output shows that once the query is executed, its value does not change:
First execution
---------------
Count: 5
Second execution
----------------
Count: 5
Although Chapter 4 explored anonymous types and how they allow you to define data types without having to formally define a class, you have not yet seen their real use. In fact, anonymous type is another new feature that Microsoft has designed with LINQ in mind.
Consider the following Contact
class definition:
public class Contact {
public int id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Suppose that you have a list containing Contact
objects, like this:
List Contacts = new List() {
new Contact() {id = 1, FirstName = "John", LastName = "Chen"},
new Contact() {id = 2, FirstName = "Maryann", LastName = "Chen" },
new Contact() {id = 3, FirstName = "Richard", LastName = "Wells" }
};
You can use LINQ to query all contacts with Chen
as the last name:
IEnumerable foundContacts =
from c in Contacts
where c.LastName == "Chen"
select c;
The foundContacts
object is of type IEnumerable
. To print out all the contacts in the result, you can use the foreach
loop:
Читать дальше