在Ruby中开始,拯救和确保?
我最近开始使用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
被调用?
是的, ensure
始终评估代码。 这就是为什么要ensure
。 所以,它finally
等于Java和C#的。
begin
/ rescue
/ else
/ ensure
/ 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
# does not change the final value of the block
end
你可以避开rescue
, ensure
或else
。 您也可以省略变量,在这种情况下,您将无法在异常处理代码中检查异常。 (好吧,你总是可以使用全局异常变量来访问引发的最后一个异常,但这有点冒险。)你可以省略异常类,在这种情况下,所有从StandardError
继承的异常都会被捕获。 (请注意,这并不意味着所有异常都会被捕获,因为有例外是Exception
实例,但不是StandardError
。大多数非常严重的异常会损害程序的完整性,如SystemStackError
, NoMemoryError
, SecurityError
, NotImplementedError
, LoadError
, SyntaxError
, ScriptError
, Interrupt
, SignalException
或SystemExit
。)
一些块形成隐含的异常块。 例如,方法定义也是隐含的异常块,所以不用写
def foo
begin
# ...
rescue
# ...
end
end
你只是写
def foo
# ...
rescue
# ...
end
要么
def foo
# ...
ensure
# ...
end
这同样适用于class
定义和module
定义。
然而,在具体的情况下,你问的是,实际上有一个更好的习惯用法。 一般情况下,当你使用最后需要清理的某些资源时,可以通过将块传递给为您执行所有清理的方法来实现此目的。 它与C#中的using
块类似,只是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
。 但它是一种普遍现象,你可以在自己的代码使用,以及用于实现任何类型的资源清理的(点菜using
在C#)或交易或任何其他你可能会想到的。
如果获取和释放资源分布在程序的不同部分,则这种情况不起作用的唯一情况。 但是如果它是本地化的,就像你的例子那样,那么你可以很容易地使用这些资源块。
顺便说一句:在现代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);
});
仅供参考,即使在rescue
部分重新生成异常,在代码执行继续到下一个异常处理程序之前,将执行ensure
块。 例如:
begin
raise "Error!!"
rescue
puts "test1"
raise # Reraise exception
ensure
puts "Ensure block"
end
如果你想确保文件关闭,你应该使用File.open
的块格式:
File.open("myFile.txt", "w") do |file|
begin
file << "#{content} n"
rescue
#handle the error here
end
end
链接地址: http://www.djcxy.com/p/4395.html