我对Swift语言非常陌生,但有C#的编程背景。
我想知道在Swift语言中是否有类似于C# using语句的等价代码。
using( var a = new MyClass()){
//Code Here
}
你可以将清理代码放在类的deinit
方法中。
在许多GC系统(如CLR上的C#)中,这是不被鼓励的,因为不能保证GC会很快(或根本不会)运行。虽然ARC有其他缺点,但这正是它的亮点:Swift的自动引用计数保证了去初始化的确定性。这与C++中的RAII完全相同。
即使抛出异常,此技术也能正常工作。
class MyClass() {
var db = openDBConnection() //example resource
deinit() {
db.close()
}
}
func foo() {
var a = MyClass()
print(a) // do stuff with a
// the (only) reference, a, will go out of scope,
// thus the instance will be deinitialized.
}
你也可以使用defer语句:
var a = MyClass()
defer { a.cleanUp() /* cleanup a however you wish */ }
你失去了像 IDisposable
这样使用接口的标准化,但你获得了能够执行任何你想要的代码的一般性。
using
会在退出块时调用类的 Dispose
方法,即使有异常也是如此。使用 defer
则需要手动编写清理代码。 - Panagiotis KanavosDispose
重载中手动编写它。我不明白你的意思。 - Baussusing
确保在退出其块时调用Dispose
。defer
不能提供这样的保证。您可以使用using
在不再需要连接时立即关闭连接。您无法使用defer执行相同的操作。 - Panagiotis Kanavosusing
只是一个语法糖,编译器会将其转换为try/finally块。这强制执行对象的处理,释放内存。如果不处理对象,则不会释放任何内存。在Swift中,我似乎理解到处理内存的方法有所不同(使用RC而不是GC),因此实际上不需要Swift版本的“using”语句,因为不存在这种语句。应该学习如何按照Alexander解释的方式处理内存。 - Phate01我正在学习Swift,遇到了同样的问题。
我找到的最接近的答案是:
if let UOW = (try UnitOfWork() as UnitOfWork?)
{
}
这是一种可选绑定的hack方法,但似乎可以工作。您需要确保您的类定义了一个与Alexander上面所述相同的deinit方法。我发现即使我的init抛出异常,只要您离开IF语句的范围,deinit方法仍然会被调用。
注意: 如果适用,确保使用弱引用以确保实际调用deinit!
对于您的作用域,使用DO块可能更符合Swift风格:
do
{
let UOW = try UnitOfWork()
// your code here
}
这种方式的好处是避免了使用块时出现“金字塔般的噩梦”(如在C#中可能会出现的情况)
using
的作用。不要指望 Swift 程序员知道using
在退出时清理了a
。 - Panagiotis KanavosDispose()
,没有其他操作。 - Alexanderdefer
的术语来解释using
。但它们是不同的语言,不同的设计,不同的语义。nothing else
保证了确定性调用并创建了一个额外的作用域。这也意味着你不需要遵循使用defer
时需要遵循的约定。这意味着编译器本身确保有一个Dispose
方法,并且它总是被调用。 - Panagiotis Kanavosusing
不会创建新的作用域。你需要自己使用{ }
显式地创建,惊喜的是,在 Swift 中你也可以这样做。这也意味着你不需要遵循使用 defer 时需要的约定 嗯?这意味着编译器本身确保有一个 Dispose 方法,并且它总是被调用 编译器对于在defer
块中调用的任何方法都会这样做,完全一样。 - Alexander