首页 > 代码库 > 9.3.1 使用 .NET 集合
9.3.1 使用 .NET 集合
9.3.1 使用 .NET 集合
到目前为止,虽然我们主要是用F# 内置的列表类型来保存数据集合,在某些情况下,使用其他的 .NET 类型,比如,System.Collections.Generic 命名空间下的 Dictionary 类,也是有用的。这种类型对需要根据键进行快速访问,特别有用,因为提供了类似功能的不可变类型(比如,F# 库中的 Map),效率低下。
需要注意的是,Dictionary 类型是可变类型,因此,像 Add 这样的方法会改变对象的状态,而不是返回新的、修改后的副本。这就是说,在需要保持代码的纯函数式的地方,使用 Dictionary 类型时,我们必须要小心。
清单 9.10 显示了如何使用 Dictionary 类型创建一个简单的查询表,以及如何用IEqualityComparer<T> 接口实现的键,指定自定义的比较方法。
汇款单 9.10 实现 IEqualityComparer<T> 接口 (F# Interactive)
> open System
openSystem.Collections.Generic;;
> let noSpaceComparer =
letreplace(s:string) = s.Replace(" ", "") <-- 从字符串中移去空格
{ newIEqualityComparer<_> with [1]
member x.Equals(a, b) = | 比较字符串,
String.Equals(replace(a), replace(b)) | 忽略空格
member x.GetHashCode(s) = |
replace(s).GetHashCode() };; |
> let scaleNames = new Dictionary<_,_>(noSpaceComparer) [2]
scaleNames.Add("100", "hundred")
scaleNames.Add("1 000", "thousand")
scaleNames.Add("1 000 000", "million");;
> scaleNames.["10 00"];;
val it : string = "thousand"
> scaleNames.["1000000"];;
val it : string = "million"
这个示例说明,当我们需要调用 .NET API,接受接口作为参数值时,对象表达式非常有用。在这里,Dictionary 类型的构造函数接[2]受IEqualityComparer<T>接口的实现作为参数值;然后,在访问保存在字典中的元素时,接口用来对键进行比较。我们创建了值 NoSpaceComparer,它实现了这个接口[1]。我们实现的是比较字符串,忽略字符串中的所有空格;我们是通过创建工具函数,从任何给定的字符串中移去空格,然后,比较修改后的字符串实现的。我们还实现了一个方法,计算字符串的哈希码,这是用于 Dictionary 类型进行高效查找的。
F# 的类型推断在这个清单中再次提供了帮助。在写对象表达式,以及创建 Dictionary 类的实例时,我们使用了下划线(_),而不是实际的类型;当编译器看到下划线,会使用其他信息,推断出参数的实际类型;在这个例子中,从代码的其他部分,能得到足够的信息。
.NET 程序员熟悉的另一个接口是IDisposable,它是用来显式清理资源的。让我们看看如何能够在 F# 中使用。
9.3.1 使用 .NET 集合