资源管理:use 关键字
本主题介绍关键字 use
和 using
函数,该函数可控制资源的初始化和发布。
“资源”这个词的用法很多。 是的,资源可以是应用程序使用的数据(例如字符串、图形等),但在此处,资源指软件或操作系统资源,例如图形设备上下文、文件句柄、网络和数据库连接、并发对象(如等待句柄等)。 应用程序对这些资源的使用涉及从操作系统或其他资源提供方获取资源,然后将资源发布到池中,以便将其提供给另一个应用程序。 当应用程序不将资源释放回公共池时,会出现问题。
若要有效且负责任地管理应用程序中的资源,必须以可预测的方式及时发布资源。 .NET Framework 通过提供 System.IDisposable
接口来帮助你满足此要求。 实现 System.IDisposable
的类型具有 System.IDisposable.Dispose
方法,该方法可正确发布资源。 适当编写的应用程序可保证在不再需要包含受限资源的任何对象时及时调用 System.IDisposable.Dispose
。 好在大多数 .NET 语言都支持对该操作的简化,F# 也不例外。 有两个有用的语言构造支持释放模式:use
绑定和 using
函数。
use
关键字具有类似于 let
绑定的形式:
使用 value = expression
它提供与 let
绑定相同的功能,但添加了对 Dispose
的调用(当值超出范围时)。 请注意,编译器对值插入 null 检查,目的是在值为 null
时不尝试调用 Dispose
。
下面的示例演示如何使用 use
关键字自动关闭文件。
open System.IO
let writetofile filename obj =
use file1 = File.CreateText(filename)
file1.WriteLine("{0}", obj.ToString() )
// file1.Dispose() is called implicitly here.
writetofile "abc.txt" "Humpty Dumpty sat on a wall."
use
的多个实例按照声明的反向顺序进行释放。 也就是说,第一个 use
将最后一个释放。
using
函数具有以下形式:
using
(expression1) function-or-lambda
在 using
表达式中,expression1 创建必须释放的对象。 expression1 的结果(必须释放的对象)成为函数或 lambda 表达式的参数、值,此处可能是预期采用单个剩余参数的函数,该参数的类型与 expression1 生成的值匹配,也可能是预期采用该类型的参数 lambda 表达式。 函数执行结束时,运行时将调用 Dispose
并释放资源(除非值为 null
),在这种情况下,不会尝试调用 Dispose。
下面的示例演示的是使用 lambda 表达式的 using
表达式。
open System.IO
let writetofile2 filename obj =
using (System.IO.File.CreateText(filename)) ( fun file1 ->
file1.WriteLine("{0}", obj.ToString() )
)
writetofile2 "abc2.txt" "The quick sly fox jumps over the lazy brown dog."
下一个示例演示使用函数的 using
表达式。
let printToFile (file1 : System.IO.StreamWriter) =
file1.WriteLine("Test output");
using (System.IO.File.CreateText("test.txt")) printToFile
请注意,该函数可能是已应用了一些参数的函数。 下面的代码示例展示了此操作。 它创建一个包含字符串 XYZ
的文件。
let printToFile2 obj (file1 : System.IO.StreamWriter) =
file1.WriteLine(obj.ToString())
using (System.IO.File.CreateText("test.txt")) (printToFile2 "XYZ")
using
函数和 use
绑定是几乎等效的方法,能达到同样的目的。 在调用 Dispose
时,using
关键字能提供更多控制。 使用 using
时,Dispose
在函数或 lambda 表达式的末尾调用;使用 use
关键字时,Dispose
在包含代码块末尾调用。 一般情况下,应首选使用 use
函数,而不是 using
函数。