Was ist der Unterschied zwischen dem Auslösen von Ausnahmen und dem Auslösen von Ausnahmen in Ruby?
Frage
Ruby verfügt über zwei verschiedene Ausnahmemechanismen:Werfen/Fangen und Heben/Retten.
Warum haben wir zwei?
Wann sollten Sie das eine verwenden und das andere nicht?
Lösung
Ich finde http://hasno.info/ruby-gotchas-and-caveats hat eine gute 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 Catch für ein bestimmtes Symbol definiert ist. Raise Rescue ist die eigentliche Ausnahmebehandlung, die das Exception-Objekt betrifft.
Andere Tipps
raise
,fail
,rescue
, Undensure
handhaben Fehler, auch bekannt als Ausnahmenthrow
Undcatch
Sind Kontrollfluss
Im Gegensatz zu anderen Sprachen werden Rubys Wurf und Fang nicht für Ausnahmen verwendet.Stattdessen bieten sie eine Möglichkeit, die Ausführung frühzeitig zu beenden, wenn keine weiteren Arbeiten erforderlich sind.(Grimm, 2011)
Beenden einer einzelnen Ebene des Kontrollflusses, z. B while
Schleife, kann mit einem einfachen durchgeführt werden return
.Das Beenden vieler Ebenen des Kontrollflusses, wie z. B. einer verschachtelten Schleife, ist möglich throw
.
Während sich der Ausnahmemechanismus „Raise and Rescue“ hervorragend eignet, um die Ausführung abzubrechen, wenn etwas schiefgeht, ist es manchmal schön, während der normalen Verarbeitung aus einem tief verschachtelten Konstrukt herausspringen zu können.Hier kommen Fangen und Werfen zum Einsatz.(Thomas und Hunt, 2001)
Verweise
- Grimm, Avdi."Wirf, fangen, heben, retten ... ich bin so verwirrt!" Rubylearning -Blog.N.p., 11. Juli 2011.Netz.1. Jan.2012. http://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/.
- Thomas, Dave und Andrew Hunt."Rubin programmieren." :Der Leitfaden für pragmatische Programmierer.N.p., 2001.Netz.29. Sept.2015. http://ruby-doc.com/docs/ProgrammingRuby/html/tut_Exceptions.html.
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise bietet eine hervorragende Erklärung, von der ich bezweifle, dass ich sie verbessern kann.Um es zusammenzufassen: Ich klaue im Laufe der Zeit einige Codebeispiele aus dem Blog-Beitrag:
raise
/rescue
sind die nächsten Analoga zumthrow
/catch
Konstrukt, mit dem Sie aus anderen Sprachen (oder dem von Python) vertraut sindraise
/except
).Wenn bei Ihnen eine Fehlerbedingung aufgetreten ist und Sie dies tun würdenthrow
darüber in einer anderen Sprache schreiben, sollten Sieraise
in Ruby.Rubys
throw
/catch
ermöglicht es Ihnen, die Ausführung zu unterbrechen und den Stapel hinaufzuklettern, um nach einem zu suchencatch
(wieraise
/rescue
tut), ist aber nicht wirklich für Fehlerbedingungen gedacht.Es sollte selten verwendet werden und dient nur dann, wenn Sie den Stapel hinaufgehen, bis Sie ein entsprechendes findencatch
„Verhalten ist für einen Algorithmus, den Sie schreiben, sinnvoll, aber es wäre nicht sinnvoll, darüber nachzudenkenthrow
als einem Fehlerzustand entsprechend.Wofür wird Fangen und Werfen in Ruby verwendet? bietet einige Vorschläge für schöne Verwendungsmöglichkeiten des
throw
/catch
bauen.
Zu den konkreten Verhaltensunterschieden zwischen ihnen gehören:
rescue Foo
wird Instanzen von rettenFoo
einschließlich Unterklassen vonFoo
.catch(foo)
wird nur fangen das gleiche Objekt,Foo
.Man kann nicht nur nicht bestehencatch
einen Klassennamen, um Instanzen davon abzufangen, aber es werden nicht einmal Gleichheitsvergleiche durchgeführt.Zum Beispielcatch("foo") do throw "foo" end
werde dir eine geben
UncaughtThrowError: uncaught throw "foo"
(oder einArgumentError
in Ruby-Versionen 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 muss verschachtelt werden...catch :foo do catch :bar do do_something_that_can_throw_foo_or_bar end end
Ein nackter
rescue
ist äquivalent zurescue StandardError
und ist ein idiomatisches Konstrukt.Ein nacktercatch
", wiecatch() {throw :foo}
, wird niemals etwas fangen und sollte nicht verwendet werden.