Answers:
我认为http://hasno.info/ruby-gotchas-and-caveats对区别有一个不错的解释:
抓/掷与加/抢不同。catch / throw允许您快速退出块,回到为特定符号定义catch的地步,引发抢救是涉及Exception对象的真正的异常处理工作。
raise
非常昂贵。throw
不是。想想throw
作为使用goto
以获得循环了。
raise
,fail
,rescue
,和ensure
手柄的错误,也被称为异常throw
和catch
是控制流与其他语言不同,Ruby的throw和catch不用于异常。相反,它们提供了一种在不需要进一步工作时及早终止执行的方法。(格林,2011年)
终止一个简单的控制流(例如while
循环)可以通过简单的完成return
。可以使用来终止许多控制流,例如嵌套循环throw
。
虽然引发异常的异常机制非常适合在出现问题时放弃执行,但是有时可以在正常处理过程中跳出一些深层嵌套的构造,这是很好的选择。这是捕捉和投掷派上用场的地方。(Thomas和Hunt,2001)
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise提供了一个很好的解释,我怀疑我可以改进。总而言之,在我走时从博客文章中切出一些代码示例:
raise
/ rescue
是您从其他语言(或Python的/ )熟悉的throw
/ catch
构造最接近的类似物。如果遇到错误情况,并且会用另一种语言进行处理,则应该使用Ruby。raise
except
throw
raise
Ruby的throw
/ catch
可以让您中断执行并爬上堆栈以查找catch
(像raise
/ rescue
确实一样),但这并不是真正意义上的错误条件。它应该很少使用,仅当“走到栈上直到找到对应的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"
(或ArgumentError
2.2之前的Ruby版本)
可以列出多个救援条款...
begin
do_something_error_prone
rescue AParticularKindOfError
# Insert heroism here.
rescue
write_to_error_log
raise
end
而多个catch
es需要嵌套...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
end
裸露rescue
等同于rescue StandardError
并且是惯用语。catch
像这样的“裸露” catch() {throw :foo}
永远不会捕获任何东西,因此不应该使用。
goto
在Ç / C ++作为@docwhat提到,Java已经标记突破和继续。(Python对此也有被拒绝的提议。)