Was ist der Unterschied - technisch, philosophisch, konzeptuell oder auf andere Weise - zwischen
raise "foo"
und
raise Exception.new("foo")
?
Was ist der Unterschied - technisch, philosophisch, konzeptuell oder auf andere Weise - zwischen
raise "foo"
und
raise Exception.new("foo")
?
Antworten:
Technisch gesehen löst der erste einen RuntimeError mit der Nachricht auf "foo"
und der zweite eine Ausnahme mit der Nachricht auf "foo"
.
In der Praxis gibt es einen signifikanten Unterschied zwischen dem Zeitpunkt, zu dem Sie den ersteren verwenden möchten, und dem Zeitpunkt, zu dem Sie den letzteren verwenden möchten.
Einfach gesagt, Sie wollen wahrscheinlich eine RuntimeError
nicht Exception
. Ein Rettungsblock ohne Argument fängt RuntimeErrors
, aber NICHT Exception
s. Wenn Sie also einen Exception
in Ihrem Code auslösen, wird dieser Code ihn nicht abfangen:
begin
rescue
end
Um das zu fangen, müssen Exception
Sie Folgendes tun:
begin
rescue Exception
end
Dies bedeutet, dass a in gewissem Sinne Exception
ein "schlimmerer" Fehler ist als a RuntimeError
, da Sie mehr Arbeit leisten müssen, um ihn zu beheben.
Was Sie wollen, hängt also davon ab, wie Ihr Projekt seine Fehler behandelt. In unseren Dämonen verfügt die Hauptschleife beispielsweise über eine leere Rettung, die sie fängt RuntimeErrors
, meldet und dann fortsetzt. Aber unter ein oder zwei Umständen möchten wir, dass der Dämon wirklich wirklich bei einem Fehler stirbt, und in diesem Fall lösen wir einen aus Exception
, der direkt durch unseren "normalen Fehlerbehandlungscode" und aus geht.
Und wieder, wenn Sie Bibliothekscode schreiben, möchten Sie wahrscheinlich einen RuntimeError
, nicht einen Exception
, da Benutzer Ihrer Bibliothek überrascht sein werden, wenn Fehler auftreten, die ein leerer rescue
Block nicht abfangen kann, und es einen Moment dauern wird, bis sie erkennen, warum.
Schließlich sollte ich sagen, dass das RuntimeError
eine Unterklasse der StandardError
Klasse ist, und die eigentliche Regel ist, dass, obwohl Sie raise
jede Art von Objekt können, das Leerzeichenrescue
standardmäßig nur alles abfängt, von dem es erbtStandardError
. Alles andere muss spezifisch sein.
StandardError
. Es muss nicht komplizierter sein als ein paar Zeilen wie class MissingArgumentsError < StandardError; end
.
Aus der offiziellen Dokumentation:
raise
raise( string )
raise( exception [, string [, array ] ] )
Löst ohne Argumente die Ausnahme in aus $!
oder löst ein RuntimeError
if aus, $!
das null ist. Mit einem einzelnen String
Argument wird ein RuntimeError
mit der Zeichenfolge als Nachricht ausgelöst. Andernfalls sollte der erste Parameter der Name einer Exception
Klasse sein (oder eines Objekts, das Exception
beim Senden eine Ausnahme zurückgibt ). Der optionale zweite Parameter legt die der Ausnahme zugeordnete Nachricht fest, und der dritte Parameter ist ein Array von Rückrufinformationen. Ausnahmen werden durch die Rettungsklausel von begin...end
Blöcken erfasst.
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
RuntimeError < StandardError < Exception
[2] daher, dass der zweite Codeblock wird sowohl eine Ausnahme fangen und eine Runtime [3] Es ist interessant / seltsam, dass "nackte" Erhöhungen und Rettungen zufällig mit dieser bestimmten Ausnahme funktionieren [4]. Vielleicht lautet die Faustregel, RuntimeError auf Client-Code zu erhöhen, aber die eigenen benutzerdefinierten Ausnahmen innerhalb des eigenen Codes zu erhöhen und zu retten.