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.
raiseist sehr teuer. throwist nicht. Stellen Sie sich vor throw, Sie verwenden goto, um aus einer Schleife herauszukommen.
raise, fail, rescue, Und ensureGriff - Fehler , auch bekannt als Ausnahmethrowund catchsind 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 whileRegelkreises 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/ rescuesind die nächsten Analoga zu dem Konstrukt throw/, catchdas Sie aus anderen Sprachen kennen (oder zu Pythons raise/ except). Wenn Sie auf eine Fehlerbedingung gestoßen sind und throwdiese in einer anderen Sprache überschreiben würden , sollten Sie dies raisein Ruby tun.
Rubys throw/ catchkönnen Sie die Ausführung brechen und den Stapel klettern für eine Suche catch(wie raise/ der rescueFall ist), ist aber nicht wirklich für Fehlerbedingungen gemeint. Es sollte selten verwendet werden und ist nur dann vorhanden, wenn das catchVerhalten "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 Foowird Instanzen der Aufnahme von FooUnterklassen von retten Foo. catch(foo)fängt nur das gleiche Objekt ,Foo . Sie können nicht nur keinen catchKlassennamen ü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 ArgumentErrorin 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 catches verschachtelt werden müssen ...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
endEin nacktes rescueist gleichbedeutend mit rescue StandardErrorund ist ein idiomatisches Konstrukt. Ein "nackter catch" catch() {throw :foo}wird niemals etwas fangen und sollte nicht verwendet werden.
gotoin C / C ++, wie @docwhat erwähnt hat, hat Java break and continue gekennzeichnet . (Python hat auch einen abgelehnten Vorschlag dafür.)