12.5.4 在 C# 中实现查询操作

在清单 12.14 中,当我们讨论序列和分析 SelectMany 操作时,已经知道可以把 C# 查询转换为方法调用。我们实现的查询,只支持以 select 子句结尾,而忽视那些仅对集合有用的情况,比如分组,这样,就需要实现 Select 扩展方法。

我们前面说过,第二个和随后的 from 子句会转换成对 SelectMany 方法的调用。当使用查询写计算时,我们使用 from 子句的方式,非常类似于F# let! 结构,表示非标准的值绑定,所以,经常会用到它,这就是说,我们还需要为 ValueWrapper <‘T> 类型实现 SelectMany 操作。

我们已经知道,SelectMany 方法对当于 bind 函数,且要稍微复杂一些,因为它有额外的函数,需要在返回结果之前运行。Select 方法更简单,但是,我们会在看过这段代码之后,再讨论,清单 12.20 实现了两个基本操作。

清单12.20 实现查询操作 (C#)

static class ValueWrapperExtensions {

public static ValueWrapper<R>Select<T, R>

(thisValueWrapper<T> source,

Func<T, R> selector) {

return newValueWrapper<R>(selector(source.Value));   <-- 用给定函数映射值

}

public static ValueWrapper<R>SelectMany<T, V, R>

(thisValueWrapper<T> source,

Func<T, ValueWrapper<V>> valueSelector,

Func<T, V, R> resultSelector) {

var newVal =valueSelector(source.Value);     [1]

var resVal = resultSelector(source.Value,newVal.Value);     [2]

return newValueWrapper<R>(resVal);    [3]

}

}

两个方法都实现为扩展方法。这就是说,当处理类型 ValueWrapper <T> 的值时,使用标准的点表示法,用于从查询语法转换期间,C# 将能够找到它们。Select 操作使用给定的函数实现映射,因此,只需要访问包装的值,运行给定的函数,然后,包装结果。

SelectMany 操作开始有点乱,但是,看一下参数的类型,还是有用的,它可以告诉我们,可以传递什么参数给什么函数。开始像 F# 的 Bind 成员一样,在提取了第一个参数值之后,通过调用由第二个参数值给定的函数[1];我们还必须把源值,与第一个函数的返回值组合起来,为了得到结果,我们以这两个值作为参数,调用第二个函数[2];最后,把结果打包成计算类型[3]],并从方法返回。

在清单 12.18 中,操作实现之后,查询表达式就能编译并运行了。在这一节,我们创建的计算类型,没有为计算增加任何额外的功能。如此简单,非常适合做成标准操作的模板。从模板开始,看看需要修改的地方,可以实现更复杂的单子类型。现在,我们把理论联系实际,为选项类型实现类似的操作。

时间: 2024-08-03 10:12:55

12.5.4 在 C# 中实现查询操作的相关文章

ES中的查询操作

1.前缀查询 先输入数据: PUT /my_index/address/1 { "postcode": "W1 3DG" } PUT /my_index/address/2 { "postcode": "W2F 8HW" } PUT /my_index/address/3 { "postcode": "W1 7HW" } PUT /my_index/address/4 { "p

Python框架学习之Flask中的数据库操作

数据库操作在web开发中扮演着一个很重要的角色,网站中很多重要的信息都需要保存到数据库中.如用户名.密码等等其他信息.Django框架是一个基于MVT思想的框架,也就是说他本身就已经封装了Model类,可以在文件中直接继承过来.但是在Flask中,并没有把Model类封装好,需要使用一个扩展包,Flask-SQLAlchemy.它是一个对数据库的抽象,让开发者不用这些编写SQL语句,而是使用其提供的接口去操作数据库,这其中涉及到一个非常重要的思想:ORM什么是ORM呢?下面我们就来详细讲解一下.

linux中如何查询端口被占用的情况

今日要运用python写一个端口勘探的小程序,以检测一些特定的效劳端口有没有被占用,突然发现自个竟然不知道在linux中怎么查询端口被占用的情况,天呐,从速学习一下. Linux如何查看端口 1.lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000 # lsof -i:8000 COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME lwfs    22065 root    6u 

LINQ:开始使用 LINQ(五)- LINQ 中的查询语法和方法语法

开始使用 LINQ(五)- LINQ 中的查询语法和方法语法 在表示语言集成查询 (LINQ) 使用 LINQ 性查询语法,文档中的多数查询编写.但是,编译代码时,必须将查询语法转换为方法,这就需要 .NET 公共语言运行时 (CLR).这些方法调用标准查询运算符的名称类似 Where.Select.GroupBy.Join.Max和 Average.可以调用这些方法直接使用方法语法而不是查询语法. 查询语法和方法语法语义相同,但是,许多人员发现查询语法更简单.更易于阅读.某些查询必须表示为方法

完善ext.grid.panel中的查询功能(紧接上一篇)

今天的代码主要是实现,Ext.grid.panel中的查询,其实我也是一名extjs新手,开始想的实现方式是另外再创建一个新的grid类来存放查询出的数据(就是有几个分类查询就创建几个grid类),这样虽然实现了,但是多写了不少代码,之后网上找到了方法. 代码如下:请结合昨天的代码看,否则你是看不明白的 /*我们操作查询的功能键是放在grid的tabbar中的,下面就是创建的grid的tabbar,其中查询操作就在其中,此代码紧接上一篇文章,这个类上一篇文章中也有,但是没有实现查询功能,红色字体

12.5.3 在 F# 中实现计算生成器

在计算表达式块前面的标识符,是类的实例,把所需的操作实现成为实例成员.许多操作都已经有了,我们根本不必要提供所有的,最基本的操作用 Bind 和 Return 成员实现.当 F# 编译器看到计算表达式,比如清单 12.18 时,会把它转换为使用这些成员的F# 代码.F# 示例转换成这样: value.Bind(ReadInt(), fun n –> value.Bind(ReadInt(), fun m–> let add = n + m let sub = n – m value.Retur

Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询

原文:Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询 如果允许在UI层直接访问Linq to Sql的DataContext,可以省去很多问题,譬如在处理多表join的时候,我们使用var来定义L2S查询,让编译器自动推断变量的具体类型(IQueryable<匿名类型>),并提供友好的智能提示:而且可以充分应用L2S的延迟加载特性,来进行动态查询.但如果我们希望将业务逻辑放在一个独立的层中(譬如封装在远程的WCF应用中),又希望在逻辑层应用Linq to sql,则情

Linq to Sql:N层应用中的查询(上) : 返回自定义实体

原文:Linq to Sql:N层应用中的查询(上) : 返回自定义实体 如果允许在UI层直接访问Linq to Sql的DataContext,可以省去很多问题,譬如在处理多表join的时候,我们使用var来定义L2S查询,让IDE自动推断变量的具体类型(IQueryable<匿名类型>),并提供友好的智能提示:而且可以充分应用L2S的延迟加载特性,来进行动态查询.但如果我们希望将业务逻辑放在一个独立的层中(譬如封装在远程的WCF应用中),又希望在逻辑层应用Linq to sql,则情况就比

day 39 mycql 查询操作,重点中的重点

数据库的查询操作是重点中的重点,最核心的内容就是它! 在MySQL管理软件中,可以通过SQL语句中的DML语言来实现数据的操作,包括 使用INSERT实现数据的插入 UPDATE实现数据的更新 使用DELETE实现数据的删除 使用SELECT查询数据以及. insert 使用方法: 1. 插入完整数据(顺序插入) 语法一: INSERT INTO 表名(字段1,字段2,字段3-字段n) VALUES(值1,值2,值3-值n); 语法二: INSERT INTO 表名 VALUES (值1,值2,