Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C# 2008 Step by Step.pdf
Скачиваний:
24
Добавлен:
25.03.2016
Размер:
13.96 Mб
Скачать

Chapter 20 Querying In-Memory Data by Using Query Expressions

389

LINQ and Deferred Evaluation

When you use LINQ to define an enumerable collection, either by using the LINQ extension methods or by using query operators, you should remember that the application does not actually build the collection at the time that the LINQ extension method is executed; the collection is enumerated only when you iterate over the collection. This means that the data in the original collection can change between executing a LINQ query and retrieving the data that the query identifies; you will always fetch the most up-to-date data. For example, the following query (which you saw earlier) defines an enumerable collection of U.S. companies:

var usCompanies = from a in addresses

where String.Equals(a.Country, “United States”) select a.CompanyName;

The data in the addresses array is not retrieved and any conditions specified in the Where filter are not evaluated until you iterate through the usCompanies collection:

foreach (string name in usCompanies)

{

Console.WriteLine(name);

}

If you modify the data in the addresses array between defining the usCompanies collection

and iterating through the collection (for example, if you add a new company based in the United States), you will see this new data. This strategy is referred to as deferred evaluation.

You can force evaluation of a LINQ query and generate a static, cached collection. This col-

lection is a copy of the original data and will not change if the data in the collection changes. LINQ provides the ToList method to build a static List object containing a cached copy of the

data. You use it like this:

var usCompanies = from a in addresses.ToList()

where String.Equals(a.Country, “United States”) select a.CompanyName;

This time, the list of companies is fixed when you define the query. If you add more U.S. companies to the addresses array, you will not see them when you iterate through the usCompanies collection. LINQ also provides the ToArray method that stores the cached collection as

an array.

In the final exercise in this chapter, you will compare the effects of using deferred evaluation of a LINQ query to generating a cached collection.

Examine the effects of deferred and cached evaluation of a LINQ query

1.Return to Visual Studio 2008, displaying the QueryBinaryTree project, and edit the Program.cs file.

390Part III Creating Components

2.Comment out the contents of the Entrance method apart from the statements that construct the empTree binary tree, as shown here:

static void Entrance()

{

Tree<Employee> empTree = new Tree<Employee>(new Employee

{Id = 1, FirstName = “Janet”, LastName = “Gates”, Department = “IT” }); empTree.Insert(new Employee

{Id = 2, FirstName = “Orlando”, LastName = “Gee”, Department = “Marketing” }); empTree.Insert(new Employee

{Id = 4, FirstName = “Keith”, LastName = “Harris”, Department = “IT” }); empTree.Insert(new Employee

{Id = 6, FirstName = “Lucy”, LastName = “Harrington”, Department = “Sales” }); empTree.Insert(new Employee

{Id = 3, FirstName = “Eric”, LastName = “Lang”, Department = “Sales” }); empTree.Insert(new Employee

{Id = 5, FirstName = “David”, LastName = “Liu”, Department = “Marketing” });

// comment out the rest of the method

...

}

Tip You can comment out a block of code by selecting the entire block in the Code and Text Editor window and then clicking the Comment Out The Selected Lines button on the

toolbar or by pressing Ctrl+E and then pressing C.

3.Add the following statements to the Entrance method, after building the empTree binary tree:

Console.WriteLine(“All employees”); var allEmployees = from e in empTree

select e;

foreach (var emp in allEmployees) Console.WriteLine(emp);

This code generates an enumerable collection of employees named allEmployees and then iterates through this collection, displaying the details of each employee.

4.Add the following code immediately after the statements you typed in the preceding step:

empTree.Insert(new Employee { Id = 7, FirstName = “Donald”, LastName = “Blanton”, Department = “IT” });

Console.WriteLine(“\nEmployee added”);

Console.WriteLine(“All employees”); foreach (var emp in allEmployees)

Console.WriteLine(emp);

These statements add a new employee to the empTree tree and then iterate through the allEmployees collection again.

Chapter 20 Querying In-Memory Data by Using Query Expressions

391

5.On the Debug menu, click Start Without Debugging. Verify that the output of the application looks like this:

All employees

Id: 1, Name: Janet Gates, Dept: IT

Id: 2, Name: Orlando Gee, Dept: Marketing

Id: 3, Name: Eric Lang, Dept: Sales

Id: 4, Name: Keith Harris, Dept: IT

Id: 5, Name: David Liu, Dept: Marketing

Id: 6, Name: Lucy Harrington, Dept: Sales

Employee added

All employees

Id: 1, Name: Janet Gates, Dept: IT

Id: 2, Name: Orlando Gee, Dept: Marketing

Id: 3, Name: Eric Lang, Dept: Sales

Id: 4, Name: Keith Harris, Dept: IT

Id: 5, Name: David Liu, Dept: Marketing

Id: 6, Name: Lucy Harrington, Dept: Sales

Id: 7, Name: Donald Blanton, Dept: IT

Notice that the second time the application iterates through the allEmployees

collection, the list displayed includes Donald Blanton, even though this employee was added only after the allEmployees collection was defined.

6.Press Enter to return to Visual Studio 2008.

7.In the Entrance method, change the statement that generates the allEmployees collection to identify and cache the data immediately, as shown here in bold:

var allEmployees = from e in empTree.ToList<Employee>( ) select e;

LINQ provides generic and nongeneric versions of the ToList and ToArray methods. If

possible, it is better to use the generic versions of these methods to ensure the type safety of the result. The data returned by the select operator is an Employee object, and the code shown in this step generates allEmployees as a generic List<Employee> collection. If you specify the nongeneric ToList method, the allEmployees collection will be a

List of object types.

8.On the Debug menu, click Start Without Debugging. Verify that the output of the application looks like this:

All employees

Id: 1, Name: Janet Gates, Dept: IT

Id: 2, Name: Orlando Gee, Dept: Marketing

Id: 3, Name: Eric Lang, Dept: Sales

Id: 4, Name: Keith Harris, Dept: IT

Id: 5, Name: David Liu, Dept: Marketing

Id: 6, Name: Lucy Harrington, Dept: Sales

Employee added

All employees

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]