9.3.2.1 用关键字 use 编程
我们已经知道,如果用关键字 use 创建值,编译器会自动在声明这个值的函数结尾,插入对 Dispose 方法的调用。这对于资源管理来说是有用的,但还有其他情况,我们需要在两个函数调用之间加包括一段代码。
假设我们希望用不同的颜色输出文本到控制台,然后,再恢复原来的颜色。用传统的方法,我们必须保存原来的颜色,设置新的颜色,发送输出到控制台,再恢复原来的颜色。
使用 use 关键字,就能完成同样的功能,但更优雅。我们可以写一个函数,改变控制台的颜色,并返回 IDisposable 值;这个值包含 Dispose 方法,调用时,恢复原来的颜色,由于有了 use 关键字,方法会自动调用。清单 9.13 显示了这个函数和对它的使用的演示。
Listing 9.13 Setting console color usingIDisposable (F# Interactive)
> open System;;
> let changeColor(clr) =
let orig =Console.ForegroundColor [1]
Console.ForegroundColor <- clr [2]
{ new IDisposablewith [3]
member x.Dispose() =
Console.ForegroundColor <- orig };; [4]
val changeColor : ConsoleColor –>IDisposable
> let hello() =
use clr =changeColor(ConsoleColor.Red) [5]
Console.WriteLine("Hello world!")
;; [6]
val hello : unit –> unit
代码中最重要的部分是 changeColor 函数。我们可以想像一下,代码包含两部分。第一部分在函数调用时立即执行,第二部分被返回,并在以后执行。代码的第一部分,首先保存原来的颜色[],然后,设置新的颜色[2]。
第二部分需要作为结果返回。我们把它作为函数返回(可能使用 lambda 函数语法),但随后,调用者将必须显式调用它。相反,我们使用对象表达式创建 IDisposable 值[3],把恢复原来颜色的代码放在 Dispose 方法中[4]。
当使用 changeColor 函数时,第一部分代码(设置新的颜色)立即执行[5]。我们使用 use 关键字保存结果,因此,在函数结的尾,Dispose 方法被调用,并恢复原来的颜色。在图 9.2 中可以看到,在 F# Interactive 控制台窗口中运行代码的结果。注意,我们必须使用独立的 F# Interactive 控制台版本,而不是集成在 Visual Studio 中的窗口,因为它不支持改变文本的颜色。
图 9.2 使用 changeColor 函数改变控制台文字的颜色。可以看到,颜色只在 Hello 函数里面改变,然后,就恢复原来颜色了。
同样的想法是在其他情况下也是非常有用的,比如,临时将图形界面中光标改变成适合“请等待”的标识,或对特定语言代码进行单元测试时,暂时把当前的线程的语言改变到特定的值。在这里的用词是暂时,说明“改变一些内容,做一些工作,再恢复原始值”的模式,非常适用于 use 关键字!
在展示面向对象特性的所有示例中,我们都使用了标准的 F# 类型,接口和对象表达式。这在以函数方式使用 F# 时,是很正常的;但是,语言还支持其他面向对象的特性。本书主要讨论函数式编程,因此,我们不会涉及所有内容,但要看几个最重要的例子。