Quelle est la différence - technique, philosophique, conceptuelle ou autre - 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")
?
Réponses:
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 voudriez utiliser le premier et le moment où vous souhaitez utiliser le second.
En termes simples, vous voulez probablement pas un RuntimeError
fichier Exception
. Un bloc de secours sans argument attrapera RuntimeErrors
, mais n'attrapera PAS Exception
s. Donc, si vous augmentez un Exception
dans votre code, ce code ne l'attrapera pas:
begin
rescue
end
Pour attraper le, Exception
vous devrez faire ceci:
begin
rescue Exception
end
Cela signifie qu'en un sens, an Exception
est une erreur "pire" que a RuntimeError
, car vous devez faire plus de travail pour vous en remettre.
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 vide qui les attrapera RuntimeErrors
, les rapportera, puis continuera. Mais dans une ou deux circonstances, nous voulons que le démon meure vraiment en cas d'erreur, et dans ce cas, nous lançons un Exception
, qui passe directement par notre "code normal de gestion des erreurs" et sort.
Et encore une fois, si vous écrivez du code de bibliothèque, vous voulez probablement un RuntimeError
, pas un Exception
, car les utilisateurs de votre bibliothèque seront surpris si cela génère des erreurs qu'un rescue
bloc vide ne peut pas détecter , et il leur faudra un moment pour comprendre pourquoi.
Enfin, je dois dire que le RuntimeError
est une sous-classe de la StandardError
classe, et la règle actuelle est que même si vous pouvez utiliser raise
n'importe quel type d'objet, le blanc rescue
ne capturera par défaut que tout ce qui hérite de StandardError
. Tout le reste doit être spécifique.
StandardError
. Cela n'a pas à être plus compliqué que quelques lignes comme class MissingArgumentsError < StandardError; end
.
De la documentation officielle:
raise
raise( string )
raise( exception [, string [, array ] ] )
Sans argument, lève l'exception $!
ou déclenche un RuntimeError
if $!
est nul. Avec un seul String
argument, il déclenche un RuntimeError
avec la chaîne comme message. Sinon, le premier paramètre doit être le nom d'une Exception
classe (ou d'un objet qui renvoie une Exception
exception lors de l'envoi). 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 capturées par la clause de sauvetage des begin...end
blocs.
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
RuntimeError < StandardError < Exception
[2] Par conséquent, ce deuxième bloc de code va attraper à la fois une exception et un RuntimeError [3] il est intéressant / étrange que la relance et le sauvetage "nus" fonctionnent avec cette exception particulière [4]. La règle de base est peut-être d'élever RuntimeError dans le code client, mais de lever et de sauver ses propres exceptions personnalisées dans son propre code?