Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Daniel Solis - Illustrated C# 2010 - 2010.pdf
Скачиваний:
16
Добавлен:
11.06.2015
Размер:
11.23 Mб
Скачать

CHAPTER 21 INTRODUCTION TO LINQ

Query Syntax and Method Syntax

There are two syntactic forms you can use when writing LINQ queries—query syntax and method syntax.

Query syntax is a declarative form that looks very much like an SQL statement. Query syntax is written in the form of query expressions.

Method syntax is an imperative form, which uses standard method invocations. The methods are from a set called the standard query operators, which will be described later in the chapter.

You can also combine both forms in a single query.

Microsoft recommends using query syntax because it’s more readable, more clearly states your query intentions, and is therefore less error-prone. There are some operators, however, that can be written only using method syntax.

Note Queries expressed using query syntax are translated by the C# compiler into method invocation form. There is no difference in runtime performance between the two forms.

542

CHAPTER 21 INTRODUCTION TO LINQ

The following code shows all three query forms. In the method syntax part, you might find that the parameter of the Where method looks a bit odd. It’s a lambda expression, as was described in Chapter 15. I’ll cover its use in LINQ a bit later in the chapter.

static void Main( )

{

int[] numbers = { 2, 5, 28, 31, 17, 16, 42 };

var numsQuery = from n

in

numbers

// Query syntax

where n <

20

 

select

n;

 

 

var numsMethod = numbers.Where(x => x < 20);

// Method syntax

int numsCount = (from n in numbers

// Combined

where n <

20

 

select

n).Count();

 

foreach (var x in numsQuery) Console.Write("{0}, ", x);

Console.WriteLine();

foreach (var x in numsMethod) Console.Write("{0}, ", x);

Console.WriteLine();

Console.WriteLine(numsCount);

}

This code produces the following output:

2, 5, 17, 16, 2, 5, 17, 16, 4

543

CHAPTER 21 INTRODUCTION TO LINQ

Query Variables

LINQ queries can return two types of results: an enumeration, which lists the items that satisfy the query parameters; or a single value, called a scalar, which is some form of summary of the results that satisfied the query.

In the following example code, the following happens:

The first statement creates an array of ints and initializes it with three values.

The second statement returns an IEnumerable object, which can be used to enumerate the results of the query.

The third statement executes a query and then calls a method (Count) that returns the count of the items returned from the query. We’ll cover operators that return scalars, such as Count, later in the chapter.

int[] numbers = { 2, 5, 28

};

 

 

 

IEnumerable<int> lowNums =

from n

in

numbers

// Returns an enumerator

 

 

where n <

20

 

 

 

select

n;

 

 

int numsCount

=

(from n in numbers

// Returns an int

 

 

where n <

20

 

 

 

select

n).Count();

 

The variable on the left of the equals sign is called the query variable. Although the types of the query variables are given explicitly in the example statements, you could also have had the compiler infer the types of the query variables by using the var keyword in place of the type names.

It’s important to understand the contents of query variables. After executing the preceding code, query variable lowNums does not contain the results of the query. Instead, it contains an object of type IEnumerable<int>, which can perform the query if it’s called upon to do so later in the code. Query variable numsCount, however, contains an actual integer value, which can have been obtained only by actually running the query.

544

CHAPTER 21 INTRODUCTION TO LINQ

The differences in the timing of the execution of the queries can be summarized as follows:

If a query expression returns an enumeration, the query is not executed until the enumeration is processed.

If the enumeration is processed multiple times, the query is executed multiple times.

If the data changes between the time the enumeration is produced and the time the query is executed, the query is run on the new data.

If the query expression returns a scalar, the query is executed immediately, and the result is stored in the query variable.

Figure 21-2 illustrates this for the enumerable query. Variable lowNums contains a reference to the enumerable that can enumerate the query results from the array.

Figure 21-2. The compiler creates an object that implements IEnumerable<int> and stores the query in

the object.

545

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