【发布时间】:2011-06-15 14:26:08
【问题描述】:
两者之间有什么区别——技术、哲学、概念或其他方面
raise "foo"
和
raise Exception.new("foo")
?
【问题讨论】:
标签: ruby exception exception-handling
两者之间有什么区别——技术、哲学、概念或其他方面
raise "foo"
和
raise Exception.new("foo")
?
【问题讨论】:
标签: ruby exception exception-handling
From the offical documentation:
raise
raise( string )
raise( exception [, string [, array ] ] )
不带参数,在$! 中引发异常,如果$! 为nil,则引发RuntimeError。使用单个 String 参数,它会引发 RuntimeError 并将字符串作为消息。否则,第一个参数应该是Exception 类的名称(或在发送异常时返回Exception 的对象)。可选的第二个参数设置与异常关联的消息,第三个参数是回调信息数组。异常被 begin...end 块的救援子句捕获。
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
【讨论】:
从技术上讲,第一个引发 RuntimeError 并将消息设置为 "foo",第二个引发一个异常并将消息设置为 "foo"。
实际上,您想要使用前者的时间和想要使用后者的时间之间存在显着差异。
简单地说,您可能需要RuntimeError 而不是Exception。没有参数的救援块将捕获RuntimeErrors,但不会捕获Exceptions。因此,如果您在代码中提出Exception,此代码将无法捕获它:
begin
rescue
end
为了赶上Exception,您必须这样做:
begin
rescue Exception
end
这意味着在某种意义上,Exception 是一个比RuntimeError 更“糟糕”的错误,因为您必须做更多的工作才能从中恢复。
所以你想要什么取决于你的项目如何处理它的错误。例如,在我们的守护进程中,主循环有一个空白救援,它将捕获RuntimeErrors,报告它们,然后继续。但在一两种情况下,我们希望守护进程真正死于错误,在这种情况下,我们会引发Exception,它会直接通过我们的“正常错误处理代码”并退出。
同样,如果您正在编写库代码,您可能需要RuntimeError,而不是Exception,因为如果它引发空白rescue 块无法捕获的错误,您的库用户会感到惊讶,他们需要一点时间才能意识到原因。
最后,我应该说RuntimeError 是StandardError 类的子类,而实际的规则是虽然你可以raise any 类型的对象,但空白的@默认情况下,987654341@ 只会捕获从StandardError 继承的任何内容。其他一切都必须具体。
【讨论】:
RuntimeError < StandardError < Exception [2] 因此,第二个代码块将捕获异常和 RuntimeError [3] 有趣/奇怪的是,“裸”引发和救援恰好与特定异常 [4] 一起工作,也许经验法则是将 RuntimeError 引发到客户端代码,但引发和救援自己的代码在自己的代码中自定义异常?
StandardError 继承的自定义错误类型。它不必比像class MissingArgumentsError < StandardError; end 这样的几行更复杂。