web-dev-qa-db-fra.com

Quelle est la différence entre `raise" foo "` et `raise Exception.new (" foo ")`?

Quelle est la différence - technique, philosophique, conceptuelle ou autre - entre

raise "foo"

et

raise Exception.new("foo")

?

97
John Bachir

Techniquement, le premier déclenche une RuntimeError avec le message défini sur "foo", et le second déclenche une exception avec le message défini sur "foo".

En pratique, il existe une différence significative entre le moment où vous souhaitez utiliser le premier et le moment où vous souhaitez utiliser le second.

Autrement dit, vous voulez probablement un RuntimeError pas un Exception. Un bloc de secours sans argument interceptera RuntimeErrors, mais n'attrapera PAS Exceptions. Donc, si vous élevez un Exception dans votre code, ce code ne l'attrapera pas:

begin
rescue
end

Afin d'attraper le Exception vous devrez faire ceci:

begin
rescue Exception
end

Cela signifie que dans un sens, une Exception est une erreur "pire" qu'une RuntimeError, car vous devez faire plus de travail pour en récupérer.

Donc, ce que vous voulez dépend de la façon dont votre projet gère ses erreurs. Par exemple, dans nos démons, la boucle principale a un sauvetage vierge qui va attraper RuntimeErrors, les signaler, puis continuer. Mais dans une ou deux circonstances, nous voulons que le démon meure vraiment vraiment sur une erreur, et dans ce cas, nous lançons un Exception, qui passe directement par notre "code de gestion d'erreur normal" et disparaît.

Et encore une fois, si vous écrivez du code de bibliothèque, vous voudrez probablement un RuntimeError, pas un Exception, car les utilisateurs de votre bibliothèque seront surpris si cela soulève des erreurs qu'un rescue block ne peut pas attraper, et il leur faudra un moment pour comprendre pourquoi.

Enfin, je dois dire que le RuntimeError est une sous-classe de la classe StandardError, et la règle actuelle est que même si vous pouvez raisen'importe lequel type d'objet, le rescue vide n'attrapera par défaut que tout ce qui hérite de StandardError. Tout le reste doit être spécifique.

115
Daniel Lucraft

De la documentation officielle:

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

Sans argument, déclenche l'exception dans $! ou lève un RuntimeError si $! est nul. Avec un seul argument String, il lève un RuntimeError avec la chaîne comme message. Sinon, le premier paramètre doit être le nom d'une classe Exception (ou un objet qui renvoie une Exception lorsqu'il est envoyé une exception). Le deuxième paramètre facultatif définit le message associé à l'exception et le troisième paramètre est un tableau d'informations de rappel. Les exceptions sont prises en compte par la clause de sauvetage de begin...end blocs.

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