资源作用域(Using)
using 将资源的生命周期限定在块作用域内:进入时拿着资源,离开块时自动调用 Dispose。文件句柄、数据库连接、事务这类文件句柄、数据库连接这类需要显式释放的资源都适用。
资源的契约:Disposable
using 的宿主类型必须实现 Disposable 协议,也就是提供一个无参的 Dispose 方法。协议经 import System.Disposable; 引入:
import System.Disposable;
class FileHandle impl Disposable
{
public var name: string;
init(n: string)
{
name = n;
print("打开", name);
}
public func Dispose()
{
print("关闭", name);
}
}三种形态
using val r = new Resource(); { } // 声明并绑定(无分号,块紧随)
using name = expr { } // 资源绑定
using expr { } // 表达式资源声明形的绑定在块内可见,块外不存在。构造实参直接写进 new,不要用对象初始化器:初始化器的 { 会和 using 的主体块混淆。
嵌套与释放顺序
using 块结束时立刻 Dispose,嵌套时按进入的逆序释放,后开的先关:
using val outer = new FileHandle("数据库")
{
using val inner = new FileHandle("事务")
{
print("使用", outer.name, "和", inner.name);
}
print("事务已关,数据库还开着");
}
print("全部关闭");打开 数据库
打开 事务
使用 数据库 和 事务
关闭 事务
事务已关,数据库还开着
关闭 数据库
全部关闭内层块一结束事务就关掉,数据库句柄留到外层块结束。这个顺序和 defer 的后进先出同构。
表达式形
不需要给资源起名字时用表达式形,块内拿不到引用,纯粹为了「进出配对」:
using new FileHandle("临时")
{
print("一次性资源");
}
print("块外继续");打开 临时
一次性资源
关闭 临时
块外继续注意
- using 的主体必须是块,
using r;单独一句是语法错误。 - Dispose 是普通方法,实现了 Disposable 的类型也可以手工调用,但用了 using 就不必手工管。
- 析构器 deinit 只在 using 退出时补调(沿基类逆序),普通块退出不触发,脚本版语言不对析构时机做承诺。
- 协议本身也能当资源类型(
using val p: P = new R()),Dispose 经协议槽分派到具体类型,前提是协议声明链里带着 Dispose 签名。
最后更新于 2026年10月10日
