首页 > 代码库 > 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 集合