什么是IDisposable
的主要目标是什么?
它只是最终化逻辑分离的设计模式吗?
它的目标很简单,是一个标准的接口来调用这个逻辑。为了提高效率,recommended implementation将处理手动处理(Dispose(true)
)与处理终止符(Dispose(false)
)中调用的Dispose分离开来 - 从终结器内部处理内部字段是多余的,因为由于终结器不能手动调用,所以我们知道它们必须已被收集。
手动处理是必需的,因为垃圾收集不是直接的(并且不能强制单独收集单个对象)。这不仅仅是一个效率问题,因为非托管资源可能不支持多个访问,所以如果第一个还没有收集,另一个访问它的对象将会失败。集合甚至没有保证,因为Ricibob显示,将代码放入一个明确的范围内并不会阻止外部对象获取自己的引用。
using
仅仅是一个自动实现的“尝试......终于”块调用预先定义的方法。
Java包括此功能作为extension of the try
statement itself。这与using
的作用相同,除了它还允许您添加自己的catch
和finally
块,而无需将其包装在其他try
块中。
Python有context managers这是一个更灵活的版本。上下文管理者可以定义特定的异常处理以及在finally
,并可能返回不同的对象比在传递 - 也就是说,这将是可能的:
with CustomDisposer(MemoryStream()) as memoryStream:
其中CustomDisposer
对象负责处置实现,但它返回MemoryStream
作为要分配给memoryStream
变量的资源。
红宝石有yield
语句,它允许一个功能wrap a code block和需要给一个参数来将挡,这样你就可以通过给定对象传递给块,然后调用部署在(相当于finally
)ensure实现这一点:
def using(o)
yield o
ensure
o.dispose
end
using MemoryStream.new do |memoryStream|
#Operate with memory stream
end
当然,因为这是一个函数定义的一部分,没有需要专用using
功能 - 它可以在例如MemoryStream.Open
方法来直接实现。
您可以在Java 7中的AutoCloseable上使用try-with-resources块:try(AutoCloseable resource = ...){...}。在Java中,析构函数不能用于此目的,因为它们可以在GC线程的任意时间被调用。 – Njol
Java提供了两个终结器和类似于'using'的东西。 Java中的终结器在C#中是不可实现的,它们唯一的用法就是在那里以防万一。 –
析构函数不在块的末尾调用。它在不确定的时间被呼叫,由GC决定。即使在C++中,如果你这样做了,析构函数也不会在块的结尾被调用。你在堆上分配一个对象,它的生命周期不限于它的范围。另一方面,在使用块的末尾调用Dispose IS。 – svinja