支持 LINQ 的 C# 功能C# Features That Support LINQ

下一节介绍 C# 3.0 中引入的新语言构造。The following section introduces new language constructs introduced in C# 3.0. 虽然这些新功能在一定程度上都用于 LINQLINQ 查询,但并不限于 LINQLINQ,如果认为有用,在任何情况下都可以使用这些新功能。Although these new features are all used to a degree with LINQLINQ queries, they are not limited to LINQLINQ and can be used in any context where you find them useful.

查询表达式Query Expressions

查询表达式使用类似于 SQL 或 XQuery 的声明性语法来查询 IEnumerable 集合。Query expressions use a declarative syntax similar to SQL or XQuery to query over IEnumerable collections. 在编译时,查询语法转换为对 LINQLINQ 提供程序的标准查询运算符扩展方法实现的方法调用。At compile time query syntax is converted to method calls to a LINQLINQ provider's implementation of the standard query operator extension methods. 应用程序通过使用 using 指令指定适当的命名空间来控制范围内的标准查询运算符。Applications control the standard query operators that are in scope by specifying the appropriate namespace with a using directive. 下面的查询表达式获取一个字符串数组,按字符串中的第一个字符对字符串进行分组,然后对各组进行排序。The following query expression takes an array of strings, groups them according to the first character in the string, and orders the groups.

var query = from str in stringArray
            group str by str[0] into stringGroup
            orderby stringGroup.Key
            select stringGroup;

有关详细信息,请参阅 LINQ 查询表达式For more information, see LINQ Query Expressions.

隐式类型化变量 (var)Implicitly Typed Variables (var)

可以使用 var 修饰符来指示编译器推断并分配类型,而不必在声明并初始化变量时显式指定类型,如下所示:Instead of explicitly specifying a type when you declare and initialize a variable, you can use the var modifier to instruct the compiler to infer and assign the type, as shown here:

var number = 5;
var name = "Virginia";
var query = from str in stringArray
            where str[0] == 'm'
            select str;

声明为 var 的变量与显式指定其类型的变量一样都是强类型。Variables declared as var are just as strongly-typed as variables whose type you specify explicitly. 通过使用 var,可以创建匿名类型,但它只能用于本地变量。The use of var makes it possible to create anonymous types, but it can be used only for local variables. 也可以使用隐式类型声明数组。Arrays can also be declared with implicit typing.

有关详细信息,请参阅隐式类型局部变量For more information, see Implicitly Typed Local Variables.

对象和集合初始值设定项Object and Collection Initializers

通过对象和集合初始值设定项,初始化对象时无需为对象显式调用构造函数。Object and collection initializers make it possible to initialize objects without explicitly calling a constructor for the object. 初始值设定项通常用在将源数据投影到新数据类型的查询表达式中。Initializers are typically used in query expressions when they project the source data into a new data type. 假定一个类名为 Customer,具有公共 NamePhone 属性,可以按下列代码中所示使用对象初始值设定项:Assuming a class named Customer with public Name and Phone properties, the object initializer can be used as in the following code:

var cust = new Customer { Name = "Mike", Phone = "555-1212" };

继续我们的 Customer 类,假设有一个名为 IncomingOrders 的数据源,并且每个订单具有一个较大的 OrderSize,我们希望基于该订单创建新的 CustomerContinuing with our Customer class, assume that there is a data source called IncomingOrders, and that for each order with a large OrderSize, we would like to create a new Customer based off of that order. 可以在此数据源上执行 LINQ 查询,并使用对象初始化来填充集合:A LINQ query can be executed on this data source and use object initialization to fill a collection:

var newLargeOrderCustomers = from o in IncomingOrders
                            where o.OrderSize > 5
                            select new Customer { Name = o.Name, Phone = o.Phone };

数据源可能具有比 Customer 类更多的属性,例如 OrderSize,但执行对象初始化后,从查询返回的数据被定型为所需的数据类型;我们选择与我们的类相关的数据。The data source may have more properties lying under the hood than the Customer class such as OrderSize, but with object initialization, the data returned from the query is molded into the desired data type; we choose the data that is relevant to our class. 因此,我们现在有填充了我们想要的多个新 CustomerIEnumerableAs a result, we now have an IEnumerable filled with the new Customers we wanted. 上述代码也可以使用 LINQ 的方法语法编写:The above can also be written in LINQ's method syntax:

var newLargeOrderCustomers = IncomingOrders.Where(x => x.OrderSize > 5).Select(y => new Customer { Name = y.Name, Phone = y.Phone });

有关详细信息,请参见:For more information, see:

匿名类型Anonymous Types

匿名类型由编译器构造,且类型名称只可用于编译器。An anonymous type is constructed by the compiler and the type name is only available to the compiler. 匿名类型提供一种在查询结果中对一组属性临时分组的简便方法,无需定义单独的命名类型。Anonymous types provide a convenient way to group a set of properties temporarily in a query result without having to define a separate named type. 使用新的表达式和对象初始值设定项初始化匿名类型,如下所示:Anonymous types are initialized with a new expression and an object initializer, as shown here:

select new {name = cust.Name, phone = cust.Phone};

有关详细信息,请参阅匿名类型For more information, see Anonymous Types.

扩展方法Extension Methods

扩展方法是一种可与类型关联的静态方法,因此可以像实例方法那样对类型调用它。An extension method is a static method that can be associated with a type, so that it can be called as if it were an instance method on the type. 实际上,利用此功能,可以将新方法“添加”到现有类型,而不会实际修改它们。This feature enables you to, in effect, "add" new methods to existing types without actually modifying them. 标准查询运算符是一组扩展方法,它们为实现 IEnumerable<T> 的任何类型提供 LINQLINQ 查询功能。The standard query operators are a set of extension methods that provide LINQLINQ query functionality for any type that implements IEnumerable<T>.

有关详细信息,请参阅扩展方法For more information, see Extension Methods.

Lambda 表达式Lambda Expressions

Lambda 表达式是一种内联函数,该函数使用 => 运算符将输入参数与函数体分离,并且可以在编译时转换为委托或表达式树。A lambda expression is an inline function that uses the => operator to separate input parameters from the function body and can be converted at compile time to a delegate or an expression tree. LINQLINQ 编程中,在对标准查询运算符进行直接方法调用时,会遇到 lambda 表达式。In LINQLINQ programming, you will encounter lambda expressions when you make direct method calls to the standard query operators.

有关详细信息,请参见:For more information, see:

请参阅See also