Ruby有两种不同的异常机制:Throw / Catch和Raise / Rescue。
为什么我们有两个?
什么时候应该使用一个而不是另一个?
答案 0 :(得分:100)
我认为http://hasno.info/ruby-gotchas-and-caveats对差异有一个不错的解释:
捕获/抛出与加注/救援不同。 catch / throw允许您快速将块退出到为特定符号定义catch的点,raise rescue是涉及Exception对象的真正异常处理。
答案 1 :(得分:95)
raise
,fail
,rescue
和ensure
处理错误,也称为例外 throw
和catch
是控制流程 与其他不同 语言,Ruby的throw和catch不用于异常。 相反,它们提供了一种在没有时提前终止执行的方法 需要进一步的工作。 (格林,2011)
终止单一级别的控制流,如while
循环,可以使用简单的return
来完成。终止许多级别的控制流,如嵌套循环,可以使用throw
完成。
虽然提升和救援的异常机制非常适合在出现问题时放弃执行,但在正常处理期间能够跳出一些深度嵌套的构造有时会很好。这就是捕获和投掷派上用场的地方。 (托马斯和亨特,2001年)
答案 2 :(得分:18)
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise提供了一个很好的解释,我怀疑我可以改进。总结一下,在我去的时候从博客文章中删除一些代码示例:
raise
/ rescue
是您与其他语言(或Python&#)熟悉的throw
/ catch
构造最接近的类似物39; s raise
/ except
)。如果您遇到错误情况,并且用另一种语言throw
覆盖它,则应该在Ruby中raise
。
Ruby throw
/ catch
可让您中断执行并爬上堆栈,寻找catch
(如raise
/ {{1但是,并不是真正意味着错误的条件。它应该很少使用,并且只是当"走到堆栈直到找到相应的rescue
"行为对于您正在编写的算法有意义,但将catch
视为与错误条件相对应是没有意义的。
What is catch and throw used for in Ruby?提供了有关throw
/ throw
构造的良好用途的一些建议。
它们之间具体的行为差异包括:
catch
将拯救rescue Foo
的实例,包括Foo
的子类。 Foo
只会抓取同一个对象catch(foo)
。你不仅不能通过Foo
一个类名来捕获它的实例,而且它甚至不会进行相等比较。例如
catch
会在2.2之前的Ruby版本中为您提供catch("foo") do
throw "foo"
end
(或UncaughtThrowError: uncaught throw "foo"
)
可以列出多个救援条款......
ArgumentError
多个begin
do_something_error_prone
rescue AParticularKindOfError
# Insert heroism here.
rescue
write_to_error_log
raise
end
es需要嵌套...
catch
裸catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
end
相当于rescue
,是一个惯用的构造。 A"裸rescue StandardError
",如catch
,永远不会抓到任何东西,不应该被使用。