Qual è la differenza tra `raise“ foo ”` e `raise Exception.new (“ foo ”)`?


Risposte:


121

Tecnicamente, il primo solleva un'eccezione RuntimeError con il messaggio impostato su "foo"e il secondo solleva un'eccezione con il messaggio impostato su "foo".

In pratica, c'è una differenza significativa tra quando si desidera utilizzare il primo e quando si desidera utilizzare il secondo.

In poche parole, probabilmente vuoi un RuntimeErrornon un file Exception. Un blocco di salvataggio senza argomento catturerà RuntimeErrors, ma NON catturerà Exceptions. Quindi, se sollevi un Exceptionnel tuo codice, questo codice non lo catturerà:

begin
rescue
end

Per catturare il Exceptiondovrai fare questo:

begin
rescue Exception
end

Ciò significa che in un certo senso an Exceptionè un errore "peggiore" di a RuntimeError, perché devi fare più lavoro per risolverlo.

Quindi ciò che vuoi dipende da come il tuo progetto gestisce gli errori. Ad esempio, nei nostri daemon, il ciclo principale ha un salvataggio vuoto che li catturerà RuntimeErrors, li segnalerà e quindi continuerà. Ma in una o due circostanze, vogliamo che il demone muoia davvero in caso di errore, e in quel caso solleviamo un Exception, che passa direttamente attraverso il nostro "normale codice di gestione degli errori" ed esce.

E ancora, se stai scrivendo il codice di una libreria, probabilmente ne vuoi una RuntimeError, non una Exception, poiché gli utenti della tua libreria saranno sorpresi se solleva errori che un rescueblocco vuoto non può rilevare, e ci vorrà un momento per capire il motivo.

Infine, dovrei dire che RuntimeErrorè una sottoclasse della StandardErrorclasse e la regola effettiva è che sebbene sia possibile raise qualsiasi tipo di oggetto, lo spazio vuoto rescueper impostazione predefinita cattura solo tutto ciò che eredita StandardError. Tutto il resto deve essere specifico.


2
molto istruttivo, grazie. un paio di cose: [1] Questo ultimo punto è stato il più illuminante, e mi ha lasciato di scoprire qualcosa IRB lei non ha citato: RuntimeError < StandardError < Exception[2], pertanto, che il secondo blocco di codice sarà catturare sia un'eccezione e un RuntimeError [3] è interessante / strano che il rilancio e il salvataggio "nudi" funzionino con quella particolare eccezione [4] forse la regola pratica è aumentare RuntimeError al codice client, ma sollevare e salvare le proprie eccezioni personalizzate all'interno del proprio codice?
John Bachir

1
[1, 2] Sì. [3] non sono sicuro ... [4] Quando sto programmando al massimo livello professionale, tendo a creare tipi di errore personalizzati che ereditano da StandardError. Non deve essere più complicato di poche righe come class MissingArgumentsError < StandardError; end.
Daniel Lucraft

Molto informativo, ma in che tipo di situazioni si vorrà lanciare un'eccezione piuttosto che un errore di runtime se si preferisce l'errore di runtime per la scrittura di libraray?
Chihung Yu

35

Dalla documentazione ufficiale:

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

Senza argomenti, solleva l'eccezione $!o solleva un RuntimeErrorse $!è nullo. Con un singolo Stringargomento, solleva un RuntimeErrorcon la stringa come messaggio. Altrimenti, il primo parametro dovrebbe essere il nome di una Exceptionclasse (o un oggetto che restituisce Exceptionun'eccezione quando viene inviata). Il secondo parametro facoltativo imposta il messaggio associato all'eccezione e il terzo parametro è una matrice di informazioni di callback. Le eccezioni sono catturate dalla clausola di salvataggio dei begin...endblocchi.

raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.