问题

我最近开始使用Ruby编程,我正在寻找异常处理.

我想知道确保是C#中的 finally 的Ruby等价物吗?我应该:

file = File.open("myFile.txt", "w")

begin
  file << "#{content} \n"
rescue
  #handle the error here
ensure
  file.close unless file.nil?
end

还是我应该这样做?

#store the file
file = File.open("myFile.txt", "w")

begin
  file << "#{content} \n"
  file.close
rescue
  #handle the error here
ensure
  file.close unless file.nil?
end

确保不管什么都被调用,即使没有引发异常吗?



解决方法

是,确保确保始终评估代码.这就是为什么它被称为确保.因此,它等同于Java和C#的 finally .

begin / rescue / else / 确保 / end 看起来像这样:

begin
  # something which might raise an exception
rescue SomeExceptionClass => some_variable
  # code that deals with some exception
rescue SomeOtherException => some_other_variable
  # code that deals with some other exception
else
  # code that runs only if *no* exception was raised
ensure
  # ensure that this code always runs, no matter what
end

您可以省略 rescue ,确保 else .您还可以省略变量,在这种情况下,您将无法在异常处理代码中检查异常. (嗯,你总是可以使用全局异常变量来访问最后引发的异常,但这是一个有点黑客.)你可以省略异常类,在这种情况下所有继承自 StandardError < / code>将被捕获. (请注意,这并不意味着所有异常都被捕获,因为有例外是异常而不是 StandardError 的实例.破坏程序完整性的严重异常,例如 SystemStackError , NoMemoryError , SecurityError , NotImplementedError LoadError , SyntaxError , ScriptError ,中断, SignalException .)

一些块形成隐式异常块.例如,方法定义也隐式地也是异常块,因此不是写

def foo
  begin
    # ...
  rescue
    # ...
  end
end

你写的只是

def foo
  # ...
rescue
  # ...
end

def foo
  # ...
ensure
  # ...
end

这同样适用于 class 定义和模块定义.

但是,在特定情况下,你问的是,实际上有一个更好的成语.一般来说,当你使用一些资源,你需要在最后清理,你这样做通过传递一个块到一个方法,为你做所有的清理.它类似于C#中使用块的,除了Ruby实际上功能强大,你不必等待微软的大祭司从山上下来,亲切地为你更换编译器.在Ruby中,你可以自己实现:

# This is what you want to do:
File.open('myFile.txt', 'w') do |file|
  file.puts content
end

# And this is how you might implement it:
def File.open(filename, mode='r', perm=nil, opt=nil)
  yield filehandle = new(filename, mode, perm, opt)
ensure
  filehandle.close unless filehandle.nil?
end

您知道的是:已经在核心库中作为 File.open 提供.但是它是一个通用的模式,你可以使用在你自己的代码,以实现任何种类的资源清理(àla 使用C#中的)或事务或任何你可能想到的. p>

如果获取和释放资源分布在程序的不同部分,则这种情况不起作用.但是,如果它是本地化的,如在你的例子,那么你可以很容易地使用这些资源块.


BTW:在现代C#中, using 实际上是多余的,因为你可以自己实现Ruby风格的资源块:

class File
{
    static T open<T>(string filename, string mode, Func<File, T> block)
    {
        var handle = new File(filename, mode);
        try
        {
            return block(handle);
        }
        finally
        {
            handle.Dispose();
        }
    }
}

// Usage:

File.open("myFile.txt", "w", (file) =>
{
    file.WriteLine(contents);
});



相关问题推荐