web-dev-qa-db-ja.com

`raise" foo "`と `raise Exception.new(" foo ")`の違いは何ですか?

違いは何ですか-技術的、哲学的、概念的、またはそうでなければ-

raise "foo"

そして

raise Exception.new("foo")

97
John Bachir

技術的には、最初は"foo"に設定されたメッセージでRuntimeErrorを発生させ、2番目は"foo"に設定されたメッセージで例外を発生させます。

実際には、前者を使用する場合と後者を使用する場合との間には大きな違いがあります。

簡単に言えば、おそらくRuntimeErrorではなくExceptionが必要でしょう。引数なしのレスキューブロックはRuntimeErrorsをキャッチしますが、Exceptionsはキャッチしません。したがって、コードでExceptionを発生させた場合、このコードはそれをキャッチしません。

begin
rescue
end

Exceptionをキャッチするには、これを行う必要があります。

begin
rescue Exception
end

これは、ある意味で、ExceptionRuntimeErrorよりも「悪い」エラーであることを意味します。回復するには、さらに多くの作業を行う必要があるためです。

したがって、どちらを望むかは、プロジェクトのエラー処理方法によって異なります。たとえば、デーモンでは、メインループに空白のレスキューがあり、RuntimeErrorsをキャッチしてレポートし、続行します。しかし、1つまたは2つの状況では、デーモンが実際にエラーで死ぬことを望みます。その場合、Exceptionを発生させます。これは、「通常のエラー処理コード」をそのまま通過します。

繰り返しますが、ライブラリコードを記述している場合は、RuntimeErrorではなくExceptionが必要です。これは、空白のrescueブロックはキャッチできず、その理由を理解するには少し時間がかかります。

最後に、RuntimeErrorStandardErrorクラスのサブクラスであり、実際のルールはraiseany typeオブジェクトの場合、空白のrescueはデフォルトでStandardErrorから継承したもののみをキャッチします。それ以外はすべて具体的でなければなりません。

115
Daniel Lucraft

公式ドキュメントから:

raise   
raise( string )
raise( exception [, string [, array ] ] )

引数なしで、$!で例外を発生させるか、$!がnilの場合にRuntimeErrorを発生させます。単一のString引数を使用すると、文字列をメッセージとしてRuntimeErrorを生成します。それ以外の場合、最初のパラメーターはExceptionクラス(または例外を送信したときにExceptionを返すオブジェクト)の名前にする必要があります。オプションの2番目のパラメーターは、例外に関連付けられたメッセージを設定し、3番目のパラメーターはコールバック情報の配列です。例外は、begin...endブロックのレスキュー句によってキャッチされます。

raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
32
ennuikiller