C#学习笔记(九):LINQ和表达式树

时间:2021-12-07 07:29:55

LINQ

LINQ:语言集成查询(Language Integrated Query)是一组用于c#和Visual Basic语言的扩展。它允许编写C#或者Visual Basic代码以查询数据库相同的方式操作内存数据。

借助于LINQ技术,我们可以使用一种类似SQL的语法来查询任何形式的数据。目前为止LINQ所支持的数据源有SQL Server、Oracle、XML(标准通用标记语言下的一个应用)以及内存中的数据集合。开发人员也可以使用其提供的扩展框架添加更多的数据源,例如MySQL、Amazon甚至是GoogleDesktop。

起源

.net的设计者在类库中定义了一系列的扩展方法来方便用户操作集合对象,而就是这些扩展方法构成了LINQ的查询操作符。

约束

LINQ的扩展方法都是针对实现IEnumerable接口的对象进行扩展的也就是说,只要实现了IEnumerable接口,就可以使用这些扩展方法。

语法

LINQ查询时有两种语法可供选择:查询表达式(Query Expression)和方法语法(Fluent Syntax)。

.NET公共语言运行库(CLR)并不具有查询表达式的概念。所以,编译器会在程序编译时把查询表达式转换为方法语法,即对扩展方法的调用。所以使用方法语法会让我们更加接近和了解LINQ的实现和本质,并且一些查询只能表示为方法调用。但另一方面,查询表达式通常会比较简单和易读。不管怎样,这两种语法是互相补充和兼容的,我们可以在一个查询中混合使用查询表达式和方法语法。

查询关键字

子句

说明

指定数据源和范围变量(类似于迭代变量)。

where

根据一个或多个由逻辑“与”和逻辑“或”运算符(&& 或 ||)分隔的布尔表达式筛选源元素。

select

指定当执行查询时返回的序列中的元素将具有的类型和形式。

group

按照指定的键值对查询结果进行分组。

into

提供一个标识符,它可以充当对 join、group 或 select 子句的结果的引用。

orderby

基于元素类型的默认比较器按升序或降序对查询结果进行排序。

join

基于两个指定匹配条件之间的相等比较来联接两个数据源。

let

引入一个用于存储查询表达式中的子表达式结果的范围变量。

in

join 子句中的上下文关键字。

on

join 子句中的上下文关键字。

equals

join 子句中的上下文关键字。

by

group 子句中的上下文关键字。

ascending

orderby 子句中的上下文关键字。

descending

orderby 子句中的上下文关键字。

语法示例

下面提供查询表达式(Query Expression)和方法语法(Fluent Syntax)两种示例,实现的效果是取出数组中的偶数。

 using System;
using System.Linq; namespace Study
{
class Program
{
private static void Main(string[] args)
{
//定义数据源
int[] nums = {, , , , , , , , , }; //使用查询表达式
var queryResult1 = from num in nums where num % == select num; foreach (int num in queryResult1)
{
Console.Write("{0,1} ", num);
} Console.WriteLine(); //使用方法语法
var queryResult2 = nums.Where(num => num % == ); foreach (int num in queryResult2)
{
Console.Write("{0,1} ", num);
} Console.Read();
}
}
}

使用LINQ操作XML

在C#3.0之前,使用的是System.Xml.XmlDocument来处理XML数据,操作稍显繁琐,下面我们看一个使用LINQ操作XML数据的例子:

 using System;
using System.Linq;
using System.Xml.Linq; namespace Study
{
class Program
{
private static string xmlString =
"<Persons>" +
"<Person Id='1'>" +
"<Name>张三</Name>" +
"<Age>18</Age>" +
"</Person>" +
"<Person Id='2'>" +
"<Name>李四</Name>" +
"<Age>28</Age>" +
"</Person>" +
"<Person Id='3'>" +
"<Name>王五</Name>" +
"<Age>38</Age>" +
"</Person>" +
"</Persons>"; private static void Main(string[] args)
{
XElement xmlDoc = XElement.Parse(xmlString); var queryResult = from element in xmlDoc.Elements("Person")
where element.Element("Name").Value == "李四"
select element; foreach (var xElement in queryResult)
{
Console.WriteLine("姓名: " + xElement.Element("Name").Value + ", Id为: " + xElement.Attribute("Id").Value);
} Console.Read();
}
}
}

LINQ的本质

LINQ在我们看来是添加了新的语法和特性,但其实对于编译器而言并没有添加任何新的东西,编写的LINQ查询语句其实在编译后会转变为编译器可以认识的Lambda表达式和扩展方法。

表达式树

表达式树是将Lambda表达式按树形结构来进行组合的一种数据结构,其主要作用是为了在LINQ中构造动态查询。

好文链接

C#中的表达式树

打造自己的LINQ Provider(上):Expression Tree揭秘

不能不说的C#特性-表达式树

掌握表达式树

C#中的Lambda表达式和表达式树

C#利用Lambda表达式树简化函数调用

用C#表达式树优雅的计算24点