我最近开始用Ruby编程,我正在研究异常处理。
我想知道ensure
是否是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
型ensure
是否无论如何都会被调用,即使没有引发异常?
7条答案
按热度按时间gfttwv5a1#
是的,
ensure
可确保始终计算代码。这就是为什么它被称为ensure
。因此,它相当于Java和C#的finally
。begin
/rescue
/else
/ensure
/end
的一般流程如下所示:字符串
您可以省略
rescue
、ensure
或else
。您也可以省略变数,在这种情况下,您将无法在异常处理程式码中检查异常。(当然,您可以始终使用全局异常变量来访问最后一个引发的异常,但这有点麻烦。)您可以省略exception类,在这种情况下,将捕获所有继承自StandardError
的异常。(请注意,这并不意味着会捕获 * 所有 * 异常,因为有些异常是Exception
的示例,而不是StandardError
的示例。大多数是危及程序完整性的非常严重的异常,例如SystemStackError
、NoMemoryError
、SecurityError
、NotImplementedError
、LoadError
、SyntaxError
、ScriptError
、Interrupt
、SignalException
或SystemExit
。)某些块形成隐式异常块。例如,方法定义也隐式地是异常块,因此不编写
型
你写的只是
型
或者是
型
这同样适用于
class
定义和module
定义。但是,在你所问的具体案例中,其实有一个好得多的成语。一般来说,当你使用一些需要在最后清理的资源时,你可以通过将一个块传递给一个为你做所有清理的方法来完成。它类似于C#中的
using
块,除了Ruby实际上足够强大,你不必等待微软的高级牧师从山上下来,慷慨地为你改变他们的编译器。在Ruby中,您可以自己实现它:型
你知道吗?这在内核库中已经作为
File.open
可用。但它是一个通用模式,您也可以在自己的代码中使用,用于实现任何类型的资源清理(在C#中为using
)或事务或您可能想到的任何其他内容。如果获取和释放资源分布在程序的不同部分,则这是唯一不起作用的情况。但是如果它是本地化的,就像在您的示例中一样,那么您可以很容易地使用这些资源块。
顺便说一句:在现代C#中,
using
实际上是多余的,因为您可以自己实现Ruby风格的资源块:型
quhf5bfb2#
仅供参考,即使在
rescue
部分重新引发异常,ensure
块也会在代码执行继续到下一个异常处理程序之前执行。例如:字符串
ljsrvy3e3#
如果你想确保一个文件被关闭,你应该使用
File.open
的块形式:字符串
xwbd5t1u4#
这就是为什么我们需要
ensure
:字符串
n3ipq98p5#
是的,
ensure
在任何情况下都会被调用。有关更多信息,请参阅《Programming Ruby》一书中的“Exceptions, Catch, and Throw”,并搜索“ensure”。zzzyeukh6#
是的,
ensure
确保它每次都运行,所以你不需要begin
块中的file.close
。顺便说一句,一个好的测试方法是:
字符串
你可以测试一下,当出现异常时,“=inside ensure block”是否会被打印出来。然后,您可以注解掉引发错误的语句,并通过查看是否打印出任何内容来查看是否执行了
ensure
语句。wz3gfoph7#
是的,
ensure
像finally
一样保证块将被执行。这对于确保关键资源得到保护非常有用,例如在出错时关闭文件句柄,或释放互斥量。