Ruby hat zwei verschiedene Ausnahmemechanismen: Werfen / Fangen und Erhöhen / Retten.
Warum haben wir zwei?
Wann sollten Sie das eine und nicht das andere verwenden?
Ruby hat zwei verschiedene Ausnahmemechanismen: Werfen / Fangen und Erhöhen / Retten.
Warum haben wir zwei?
Wann sollten Sie das eine und nicht das andere verwenden?
Antworten:
Ich denke, http://hasno.info/ruby-gotchas-and-caveats hat eine anständige Erklärung für den Unterschied:
Fangen / Werfen ist nicht dasselbe wie Erhöhen / Retten. Mit catch / throw können Sie Blöcke schnell bis zu einem Punkt verlassen, an dem ein Fang für ein bestimmtes Symbol definiert ist. Raise Rescue ist die eigentliche Ausnahmebehandlung für das Exception-Objekt.
raise
ist sehr teuer. throw
ist nicht. Stellen Sie sich vor throw
, Sie verwenden goto
, um aus einer Schleife herauszukommen.
raise
, fail
, rescue
, Und ensure
Griff - Fehler , auch bekannt als Ausnahmethrow
und catch
sind KontrollflussIm Gegensatz zu anderen Sprachen werden Rubys Wurf und Fang nicht für Ausnahmen verwendet. Stattdessen bieten sie eine Möglichkeit, die Ausführung vorzeitig zu beenden, wenn keine weiteren Arbeiten erforderlich sind. (Grimm, 2011)
Das Beenden einer einzelnen Ebene des Kontrollflusses wie eines while
Regelkreises kann mit einem einfachen Vorgang erfolgen return
. Das Beenden vieler Ebenen des Kontrollflusses, wie z. B. einer verschachtelten Schleife, kann durchgeführt werden throw
.
Während der Ausnahmemechanismus von Raise and Rescue großartig ist, um die Ausführung abzubrechen, wenn etwas schief geht, ist es manchmal schön, während der normalen Verarbeitung aus einem tief verschachtelten Konstrukt herausspringen zu können. Hier bieten sich Fangen und Werfen an. (Thomas und Hunt, 2001)
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise bietet eine hervorragende Erklärung, die ich nicht verbessern kann. Zusammenfassend lässt sich sagen, dass ich einige Codebeispiele aus dem Blog-Beitrag geklaut habe:
raise
/ rescue
sind die nächsten Analoga zu dem Konstrukt throw
/, catch
das Sie aus anderen Sprachen kennen (oder zu Pythons raise
/ except
). Wenn Sie auf eine Fehlerbedingung gestoßen sind und throw
diese in einer anderen Sprache überschreiben würden , sollten Sie dies raise
in Ruby tun.
Rubys throw
/ catch
können Sie die Ausführung brechen und den Stapel klettern für eine Suche catch
(wie raise
/ der rescue
Fall ist), ist aber nicht wirklich für Fehlerbedingungen gemeint. Es sollte selten verwendet werden und ist nur dann vorhanden, wenn das catch
Verhalten "Gehen Sie den Stapel hinauf, bis Sie ein entsprechendes Verhalten finden " für einen Algorithmus, den Sie schreiben, Sinn macht, aber es wäre nicht sinnvoll, an das zu denkenthrow
als einem Fehler entsprechend vorzustellen Bedingung.
Wofür wird in Ruby Fangen und Werfen verwendet? bietet einige Vorschläge für nette Verwendungen des throw
/ catch
-Konstrukts.
Die konkreten Verhaltensunterschiede zwischen ihnen umfassen:
rescue Foo
wird Instanzen der Aufnahme von Foo
Unterklassen von retten Foo
. catch(foo)
fängt nur das gleiche Objekt ,Foo
. Sie können nicht nur keinen catch
Klassennamen übergeben, um Instanzen davon abzufangen, sondern auch keine Gleichheitsvergleiche durchführen. Zum Beispiel
catch("foo") do
throw "foo"
end
gibt Ihnen eine UncaughtThrowError: uncaught throw "foo"
(oder eine ArgumentError
in Versionen von Ruby vor 2.2)
Es können mehrere Rettungsklauseln aufgeführt werden ...
begin
do_something_error_prone
rescue AParticularKindOfError
# Insert heroism here.
rescue
write_to_error_log
raise
end
während mehrere catch
es verschachtelt werden müssen ...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
end
Ein nacktes rescue
ist gleichbedeutend mit rescue StandardError
und ist ein idiomatisches Konstrukt. Ein "nackter catch
" catch() {throw :foo}
wird niemals etwas fangen und sollte nicht verwendet werden.
goto
in C / C ++, wie @docwhat erwähnt hat, hat Java break and continue gekennzeichnet . (Python hat auch einen abgelehnten Vorschlag dafür.)