我知道你的设计是无法控制对象被销毁时会发生什么。我也知道将一些类方法定义为终结器。

然而,C ++的RAII的ruby习惯用法(资源在构造函数中初始化,在析构函数中关闭)?即使出现错误或异常,人们如何管理对象内部使用的资源?

使用确保有效:

f = File.open("testfile")
begin
  # .. process
rescue
  # .. handle error
ensure
  f.close unless f.nil?
end

但是每次需要调用open方法时,类的用户必须记住要执行整个begin-rescue-ensure chacha

例如,我将拥有以下类:

class SomeResource
 def initialize(connection_string)
   @resource_handle = ...some mojo here...
 end

 def do_something()
   begin
    @resource_handle.do_that()
    ...
   rescue
    ...
   ensure
 end

 def close
  @resource_handle.close
 end

end

如果异常是由其他某些类引起并且脚本退出,则不会关闭resource_handle。

或者问题是我还在做这个C ++一样吗?

有帮助吗?

解决方案

所以用户不要“必须记住做整个开始救援 - 确保chacha ”将 rescue / yield 结合使用

class SomeResource
  ...
  def SomeResource.use(*resource_args)
    # create resource
    resource = SomeResource.new(*resource_args) # pass args direct to constructor
    # export it
    yield resource
  rescue
    # known error processing
    ...
  ensure
    # close up when done even if unhandled exception thrown from block
    resource.close
  end
  ...
end

客户端代码可以按如下方式使用它:

SomeResource.use(connection_string) do | resource |
  resource.do_something
  ... # whatever else
end
# after this point resource has been .close()d

事实上,这就是 File.open 的运作方式 - 让第一个答案充其量混淆(好吧是我的工作同事)。

File.open("testfile") do |f|
  # .. process - may include throwing exceptions
end
# f is guaranteed closed after this point even if exceptions are 
# thrown during processing

其他提示

如何将产生资源发送到块?例如:

File.open("testfile") do |f|
  begin
    # .. process
  rescue
    # .. handle error
  end
end
  

或者问题是我还在做这个C ++一样吗?

是的,因为在C ++资源中,对于堆栈中的所有内容都会隐式发生释放。堆栈展开=资源被破坏= destructors被调用,从那里可以释放东西。由于Ruby没有析构函数,因此当“其他所有内容都完成”时,不会“执行此操作”。因为垃圾收集可能会延迟几个周期。你确实有终结者,但他们被称为“处于不确定状态”。 (并非一切都可供他们使用)并且他们会被GC调用。

因此,如果你持有一些最好被释放的资源的句柄,你需要明确地释放它。事实上,处理这种情况的正确习惯是

def with_shmoo
  handle = allocate_shmoo
  yield(handle)
ensure
  handle.close
end

请参阅 http://www.rubycentral.com/pickaxe/tut_exceptions.html

在Ruby中,您将使用 ensure 语句:

f = File.open("testfile")
begin
  # .. process
rescue
  # .. handle error
ensure
  f.close unless f.nil?
end

Python,Java或C#的用户会熟悉它,就像try / catch / finally一样。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top