12.4.1 自定义查询表达式

来源:互联网 发布:linux元字符 编辑:程序博客网 时间:2024/06/06 00:50
 

12.4.1 自定义查询表达式

 

    原则上,我们可以使用查询处理任何支持绑定操作的类型。这是用于函数式编程中的标准名称,像上一节中所示的类型签名的函数。从技术角度讲,我们需要实现可以由 C# 编译器所使用的方法,把查询表达式转换为标准的函数调用。我们将为 12.6 节中的 Option<T> 的类型实现这些方法。该类型没有实现 IEnumerable<T>,所以,标准查询运算符不能使用。

    让我们首先考虑一下,查询应用于选项类型意谓着什么。清单 12.15 显示了两个查询。左边一个处理列表,右边一个处理选项类型。我们将使用两个简单的函数来提供输入:ReadIntList 函数读取整数列表 (类型为 List<int>),TryReadInt 返回选项值(类型为 Option<int>)。

 

Listing 12.15 Using queries with lists and option values (C#)

 

var list =
  from n in ReadIntList()
  from m in ReadIntList()
  select n * m;

var option =
  from n in TryReadInt()
  from m in TryReadInt()
  select n * m;

 

    除了处理的数据类型不同之外,查询完全相同,因此,它们使用不同的查询运算符实现。两个都读取不同的输入,并返回输入整数的积。表 12.1 给出了输入的样例,并显示了结果。

 

表 12.1 对于可能的不同输入,由处理列表和选项值的查询所产生的结果

Type of valuesInput #1Input #2Output

Lists
Options
Options
Options

[2; 3]
Some(2)
Some(3)
None

[10; 100]
Some(10)
None
Not required

[20; 200; 30; 300]
Some(20)
None
None

 

    对于列表,查询执行交叉联接运算(可以想象成在 F# 的序列表达式中,两个嵌套的 for 循环),它会产生一个序列,由输入值的每种组合的条目所组成。对于选项值,有三种可能性。

    ■ 当第一个输入是值时,我们要看第二个。然后,根据第二个输入的不同,会发生以下两种情况:

      — 如果第二个输入也是一个值,则结果也是 Some 值,包含的结果是积。

      — 如果第二个输入是 None,由于没有值相乘,这样,查询返回 None。

    ■ 第一个输入为 None 时,我们知道这个结果无需第二输入。整个查询延迟执行,所以,我们不必去读第二输入:TryReadInt 函数只调用一次。

    正如你所看到的,查询表达式提供了一种简便的方法,来处理选项值。清单 12.15 肯定要比我们在第 6 章中看到的等价代码,容易写 (和读),在那儿,我们显式地使用了高阶函数。在本章的后面,我们将会看到,如何实现所有必要的查询运算符,不过,我们还是先看一下在 F# 中的类似语法。

 

原创粉丝点击