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

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)两种示例,实现的效果是取出数组中的偶数。

 1 using System;
 2 using System.Linq;
 3
 4 namespace Study
 5 {
 6     class Program
 7     {
 8         private static void Main(string[] args)
 9         {
10             //定义数据源
11             int[] nums = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
12
13             //使用查询表达式
14             var queryResult1 = from num in nums where num % 2 == 0 select num;
15
16             foreach (int num in queryResult1)
17             {
18                 Console.Write("{0,1} ", num);
19             }
20
21             Console.WriteLine();
22
23             //使用方法语法
24             var queryResult2 = nums.Where(num => num % 2 == 0);
25
26             foreach (int num in queryResult2)
27             {
28                 Console.Write("{0,1} ", num);
29             }
30
31             Console.Read();
32         }
33     }
34 }

使用LINQ操作XML

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

 1 using System;
 2 using System.Linq;
 3 using System.Xml.Linq;
 4
 5 namespace Study
 6 {
 7     class Program
 8     {
 9         private static string xmlString =
10             "<Persons>" +
11             "<Person Id=‘1‘>" +
12             "<Name>张三</Name>" +
13             "<Age>18</Age>" +
14             "</Person>" +
15             "<Person Id=‘2‘>" +
16             "<Name>李四</Name>" +
17             "<Age>28</Age>" +
18             "</Person>" +
19             "<Person Id=‘3‘>" +
20             "<Name>王五</Name>" +
21             "<Age>38</Age>" +
22             "</Person>" +
23             "</Persons>";
24
25         private static void Main(string[] args)
26         {
27             XElement xmlDoc = XElement.Parse(xmlString);
28
29             var queryResult = from element in xmlDoc.Elements("Person")
30                 where element.Element("Name").Value == "李四"
31                 select element;
32
33             foreach (var xElement in queryResult)
34             {
35                 Console.WriteLine("姓名: " + xElement.Element("Name").Value + ", Id为: " + xElement.Attribute("Id").Value);
36             }
37
38             Console.Read();
39         }
40     }
41 }

LINQ的本质

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

表达式树

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

好文链接

C#中的表达式树

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

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

掌握表达式树

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

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

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

时间: 2024-08-01 09:41:49

C#学习笔记(九):LINQ和表达式树的相关文章

angular学习笔记(九)-css类和样式3

再来看一个选择li列表的例子: 点击li中的任意项,被点击的li高亮显示: <!DOCTYPE html> <html ng-app> <head> <title>6.3css类和样式</title> <meta charset="utf-8"> <script src="../angular.js"></script> <script src="scri

angular学习笔记(九)-css类和样式2

在上一个例子中,元素的类名使用拼接的方法,这样,类名中就不得不带有true或false,并且不易维护,所以,angular使用ng-class属性来控制元素的类名: 我们来看一个小例子,点击error按钮,顶部提示错误框,点击warning按钮,顶部提示警告框. 错误框的类名是.err,警告框的类名是.warn: <!DOCTYPE html> <html ng-app> <head> <title>6.2css类和样式</title> <

APUE 学习笔记(九) 高级I/O

1. 非阻塞I/O 低速系统调用时可能会使进程永远阻塞的一类系统调用,包括以下调用: (1)某些文件类型你(网络socket套接字.终端设备.管道)暂无可使用数据,则读操作可能会使调用者永远阻塞 (2)如果数据不能立即被(1)中文件类型接受,则写操作会使调用者永远阻塞 (3)某些进程间通信函数 非阻塞I/O使我们可以调用open.read.write这样的I/O操作,并使这些操作不会永远阻塞,如果这种操作不能完成,则调用立即出错返回 对于一个给定的文件有两种方法对其指定非阻塞I/O: (1)调用

python学习笔记九——文件与目录

1.python进行文件读写的函数是open或file类 mode:r  只读 r+   读写 w  写入,先删除原文件,再重新写入,如果文件没有则创建 w+  读写,先删除原文件,再重新写入,如果文件没有则创建(可写入和输出) a  写入,在文件末尾追加新的内容,文件不存在则创建 a+  读写,在文件末尾追加新的内容,文件不存在则创建 b  打开二进制文件,可与r,w,a,+结合使用 U  支持所有的换行符号,"\r","\n","\r\n"

JavaScript学习笔记【2】表达式和运算符、语句、对象

笔记来自<JavaScript权威指南(第六版)> 包含的内容: 表达式和运算符 语句 对象 表达式和运算符 数组直接量中的列表逗号之间的元素可以省略,这时省略的空位会填充值undefined.元素列表末尾可以留下单个逗号,这时并不会创建一个新的值为undefined元素. 属性访问表达式,.identifier的写法只适用于要访问的属性名称是合法的标识符,并且需要知道要访问的属性的名字.如果属性名称是一个保留字或者包含空格和标识符,或是一个数字(对于数组来说),则必须使用方括号的写法.当属性

Linux System Programming 学习笔记(九) 内存管理

1. 进程地址空间 Linux中,进程并不是直接操作物理内存地址,而是每个进程关联一个虚拟地址空间 内存页是memory management unit (MMU) 可以管理的最小地址单元 机器的体系结构决定了内存页大小,32位系统通常是 4KB, 64位系统通常是 8KB 内存页分为 valid or invalid: A valid page is associated with an actual page of data,例如RAM或者磁盘上的文件 An invalid page is

虚拟机VMWare学习笔记九 - 物理机上的文件挂载到虚拟机上

物理机上的文件夹或盘符直接挂载到虚拟机上使用. VM -- Settings Options -- Shared Folders -- 勾选Always enabled , 勾选Map as a network drive in Windows guests 在点击下面的添加来添加共享的文件夹 选择路径 可以看到虚拟机中的共享文件夹已经出现在Windows 中了 虚拟机VMWare学习笔记九 - 物理机上的文件挂载到虚拟机上

初探swift语言的学习笔记九(OC与Swift混编)

swift 语言出来后,可能新的项目直接使用swift来开发,但可能在过程中会遇到一些情况,某些已用OC写好的类或封装好的模块,不想再在swift 中再写一次,哪就使用混编.这个在IOS8中是允许的. 先中简单的入手,先研究在同一个工程目录下混合使用的情况. 为了演示.先准备两个类 第一个是swift语言写的类,文件名为 act.swift import Foundation class Act : NSObject { func hasAct(tag:Int) -> String { swit

《Hibernate学习笔记九》:多对一和一对多的关联关系

<Hibernate学习笔记九>:多对一和一对多的关联关系 前面介绍了一对一的关联关系在Hibernate应该如何来实现,这篇博文就来介绍下多对一和一对多的关联关系. 多对一和一对多的关联关系在我们的生活中也比较常见,例如,在我们学生时代,一个班级可以有多个学生,而一个学生只能属于一个班级,这就是一个多对一(一对多)的例子: 还有在我们的工作中,一个工作小组可以有多个用户,而一个用户只能属于一个小组,这也是一个多对一(一对多)的关系的例子. 1.多对一的单向关联关系 下面就以一个工作小组可以有