Ruby 有两种不同的异常机制:Throw/Catch 和 Raise/Rescue。
为什么我们有两个?
什么时候应该使用一个而不是另一个?
raise, fail, rescue, 和ensure处理错误,也称为异常throw并且catch是控制流与其他语言不同,Ruby 的 throw 和 catch 不用于异常。相反,它们提供了一种在不需要进一步工作时提前终止执行的方法。(格林,2011)
while可以使用简单的return. 终止多层控制流,如嵌套循环,可以使用throw.
虽然 raise 和 rescue 的异常机制非常适合在出现问题时放弃执行,但在正常处理期间能够跳出一些深度嵌套的构造有时会很好。这就是 catch 和 throw 派上用场的地方。(托马斯和亨特,2001)
我认为http://hasno.info/ruby-gotchas-and-caveats对差异有一个不错的解释:
接/投与举/救不同。catch/throw 允许您将块快速退出到为特定符号定义捕获的点,引发救援是涉及 Exception 对象的真正异常处理内容。
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise提供了一个很好的解释,我怀疑我可以改进。总而言之,我从博客文章中截取了一些代码示例:
raise/是您从其他语言(或 Python 的/ )熟悉的/构造rescue最接近的类似物。如果您遇到了错误情况并且您将使用另一种语言来解决它,那么您应该使用 Ruby。throwcatchraiseexceptthrowraise
Ruby 的throw/catch让你中断执行并爬上堆栈寻找catch(like raise/ rescuedos),但实际上并不意味着错误条件。它应该很少使用,并且仅用于当“遍历堆栈直到找到相应的catch”行为对您正在编写的算法有意义但将其throw视为对应于错误是没有意义的健康)状况。
Ruby 中的 catch 和 throw 有什么用?throw提供了一些关于/catch构造的好用的建议。
它们之间的具体行为差异包括:
rescue Foo将拯救Foo包括Foo. catch(foo)只会捕获相同的对象,Foo . 您不仅不能传递catch类名来捕获它的实例,而且它甚至不会进行相等比较。例如
catch("foo") do
throw "foo"
end
会给你一个UncaughtThrowError: uncaught throw "foo"(或ArgumentError2.2 之前的 Ruby 版本)
可以列出多个救援条款...
begin
do_something_error_prone
rescue AParticularKindOfError
# Insert heroism here.
rescue
write_to_error_log
raise
end
而多个catches需要嵌套...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
end
一个barerescue等价于rescue StandardError并且是一个惯用的构造。“裸catch”,如catch() {throw :foo},永远不会捕获任何东西,也不应该使用。