在技术上、哲学上、概念上或其他方面,这些之间有什么不同呢?
raise "foo"
and
raise Exception.new("foo")
?
从技术上讲,第一个会引发一个RuntimeError,消息内容为"foo"
,而第二个会引发一个Exception,消息内容也为"foo"
。
实际上,在你想使用前者和后者之间有很大的区别。
简单来说,你可能需要一个RuntimeError
而不是Exception
。没有参数的rescue块可以捕获RuntimeErrors
,但不会捕获Exception
s。所以如果你在代码中引发了一个Exception
,这段代码将无法捕获它:
begin
rescue
end
要捕获Exception
,您需要执行以下操作:
begin
rescue Exception
end
这意味着在某种意义上,Exception
比RuntimeError
更严重,因为您需要更多的工作来从中恢复过来。rescue
块,可以捕获RuntimeErrors
、报告错误,然后继续执行。但在一两种情况下,我们希望守护进程真的遇到错误时能够立即停止运行,在这种情况下,我们会引发一个Exception
,它会直接通过我们的“常规错误处理代码”并退出。RuntimeError
而不是Exception
,因为您的库的用户将感到惊讶,如果它引发了一个空的rescue
块无法捕获的错误,并且他们需要一段时间才能意识到原因所在。RuntimeError
是StandardError
类的子类,实际规则是尽管您可以raise
任何类型的对象,但空的rescue
默认只会捕获任何继承自StandardError
的错误。其他所有类型都必须是具体的类型。raise
raise( string )
raise( exception [, string [, array ] ] )
当没有参数时,会抛出$!
中的异常,如果$!
为nil,则抛出RuntimeError
异常。当传入单个String
参数时,它将抛出一个带有该字符串作为消息的RuntimeError
异常。否则,第一个参数应该是一个Exception
类的名称(或发送异常返回Exception
对象的对象)。可选的第二个参数设置与异常相关联的消息,第三个参数是回调信息的数组。异常由begin...end
块的rescue子句捕获。
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
RuntimeError < StandardError < Exception
[2] 因此,第二个代码块将捕获Exception和RuntimeError [3] 有趣/奇怪的是,“裸”raise和rescue恰好可以使用该特定异常 [4] 或许经验法则是将RuntimeError抛给客户端代码,但在自己的代码中引发和捕获自定义异常? - John BachirStandardError
继承的自定义错误类型。它不必比class MissingArgumentsError < StandardError; end
更复杂。 - Daniel Lucraft