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

CHAPTER 21 INTRODUCTION TO LINQ

LINQ Providers

In the previous example, the data source was simply an array of ints, which is an in-memory object of the program. LINQ, however, can work with many different types of data sources, such as SQL databases, XML documents, and a host of others. For every data source type, however, under the covers there must be a module of code that implements the LINQ queries in terms of that data source type. These code modules are called LINQ providers. The important points about LINQ providers are the following:

Microsoft provides LINQ providers for a number of common data source types, as shown in Figure 21-1.

You can use any LINQ-enabled language (C# in our case) to query any data source type for which there is a LINQ provider.

New LINQ providers are constantly being produced by third parties for all sorts of data source types.

Figure 21-1. The architecture of LINQ, the LINQ-enabled languages, and LINQ providers

There are entire books dedicated to LINQ in all its forms and subtleties, but that’s clearly beyond the scope of this chapter. Instead, this chapter will introduce you to LINQ and explain how to use it with program objects (LINQ to Objects) and XML (LINQ to XML).

539

CHAPTER 21 INTRODUCTION TO LINQ

Anonymous Types

Before getting into the details of LINQ’s querying features, I’ll start by covering a language feature that allows you to create unnamed class types. These are called, not surprisingly, anonymous types.

In Chapter 6 we covered object initializers, which is the construct that allows you to initialize the fields and properties of a new class instance when using an object-creation expression. Just to remind you, this kind of object-creation expression consists of three components: the keyword new, the class name or constructor, and the object initializer. The object initializer consists of a comma-separated list of member initializers between a set of curly braces.

Creating a variable of an anonymous type uses the same form—but without the class name or constructor. The following line of code shows the object-creation expression form of an anonymous type:

Object initializer

new { FieldProp = InitExpr, FieldProp = InitExpr, ...}

 

Member initializer

 

Member initializer

The following code shows an example of creating and using an anonymous type. It creates a variable called student, with an anonymous type that has three string properties and one int property. Notice in the WriteLine statement that the instance’s members are accessed just as if they were members of a named type.

static void Main( )

{

var student = new {LName="Jones", FName="Mary", Age=19, Major="History"};

Must use var

Object initializer

Console.WriteLine("{0} {1}, Age {2}, Major: {3}", student.FName, student.LName, student.Age, student.Major);

}

This code produces the following output:

Mary Jones, Age 19, Major: History

Important things to know about anonymous types are the following:

Anonymous types can be used only with local variables—not with class members.

Since an anonymous type doesn’t have a name, you must use the var keyword as the variable type.

540

CHAPTER 21 INTRODUCTION TO LINQ

When the compiler encounters the object initializer of an anonymous type, it creates a new class type with a private name that it constructs. For each member initializer, it infers its type and creates a private variable of that type in the new class, and it creates a read/write property to access the variable. The property has the same name as the member initializer. Once the anonymous type is constructed, the compiler creates an object of that type.

Besides the assignment form of member initializers, anonymous type object initializers also allow two other forms: simple identifiers and member access expressions. These two forms are called projection initializers. The following variable declaration shows all three forms. The first member initializer is in the assignment form. The second is an identifier, and the third is a member access expression.

var student = new { Age = 19, Major, Other.Name };

For example, the following code uses all three types. Notice that the projection initializers must be defined before the declaration of the anonymous type. Major is a local variable, and Name is a static field of class Other.

class Other

{

static public string Name = "Mary Jones";

}

class Program

 

{

 

static void Main()

 

{

 

string Major = "History";

 

Assignment form

Identifier

var student = new { Age = 19, Other.Name, Major};

Member access

Console.WriteLine("{0}, Age {1}, Major: {2}", student.Name, student.Age, student.Major);

}

}

This code produces the following output:

Mary Jones, Age 19, Major: History

The projection initializer form of the object initializer just shown has exactly the same result as the assignment form shown here:

var student = new { Age = Age, Name = Other.Name, Major = Major};

Although your code cannot see the anonymous type, it’s visible to object browsers. If the compiler encounters another anonymous type with the same parameter names, with the same inferred types, and in the same order, it will reuse the type and create a new instance—not create a new anonymous type.

541

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