Qual é a diferença entre `raise“ foo ”` e `raise Exception.new (“ foo ”)`?


Respostas:


121

Tecnicamente, o primeiro gera um RuntimeError com a mensagem definida como "foo"e o segundo gera uma Exceção com a mensagem definida como "foo".

Praticamente, há uma diferença significativa entre quando você deseja usar o primeiro e quando deseja usar o último.

Simplificando, você provavelmente RuntimeErrornão deseja um Exception. Um bloco de resgate sem um argumento pegará RuntimeErrors, mas NÃO pegará Exceptions. Portanto, se você gerar um Exceptionem seu código, este código não o pegará:

begin
rescue
end

Para capturar o, Exceptionvocê terá que fazer o seguinte:

begin
rescue Exception
end

Isso significa que, em certo sentido, um Exceptioné um erro "pior" do que um RuntimeError, porque você precisa trabalhar mais para se recuperar dele.

Portanto, o que você deseja depende de como seu projeto trata de erros. Por exemplo, em nossos daemons, o loop principal tem um resgate em branco que os captura RuntimeErrors, relata e depois continua. Mas em uma ou duas circunstâncias, queremos que o daemon realmente morra com um erro e, nesse caso, levantamos um Exception, que vai direto ao nosso "código normal de tratamento de erros" e sai.

E, novamente, se você está escrevendo o código da biblioteca, provavelmente deseja um RuntimeError, não um Exception, pois os usuários de sua biblioteca ficarão surpresos se isso gerar erros que um rescuebloco em branco não pode detectar, e eles levarão um momento para perceber o porquê.

Finalmente, devo dizer que RuntimeErroré uma subclasse da StandardErrorclasse, e a regra real é que, embora você possa raise qualquer tipo de objeto, o espaço rescueem branco , por padrão, só capturará qualquer coisa que herde de StandardError. Todo o resto tem que ser específico.


2
muito informativo, obrigado. algumas coisas: [1] Esse último parágrafo foi o mais esclarecedor, e deixe-me descobrir em algo IRB você não mencionou: RuntimeError < StandardError < Exception[2] portanto, que segundo bloco de código vai pegar tanto uma exceção e uma RuntimeError [3] é interessante / estranho que o aumento e o resgate "simples" aconteçam para funcionar com aquela Exception em particular [4]. Talvez a regra seja aumentar RuntimeError para o código do cliente, mas aumentar e resgatar as próprias Exceptions personalizadas dentro do próprio código?
John Bachir

1
[1, 2] Sim. [3] não tenho certeza ... [4] Quando estou programando no meu nível mais profissional, tendo a criar tipos de erros personalizados que herdam de StandardError. Não precisa ser mais complicado do que algumas linhas como class MissingArgumentsError < StandardError; end.
Daniel Lucraft

Muito informativo, mas em que tipo de situações você desejará lançar uma Exceção em vez de erro de tempo de execução se o erro de tempo de execução for preferido para escrever bibliotecários?
Chihung Yu

35

Da documentação oficial:

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

Sem argumentos, levanta a exceção em $!ou levanta um RuntimeErrorse $!for nulo. Com um único Stringargumento, ele gera a RuntimeErrorcom a string como uma mensagem. Caso contrário, o primeiro parâmetro deve ser o nome de uma Exceptionclasse (ou um objeto que retorna uma Exceptionexceção quando enviada). O segundo parâmetro opcional define a mensagem associada à exceção e o terceiro parâmetro é uma matriz de informações de retorno de chamada. As exceções são capturadas pela cláusula de resgate de begin...endblocos.

raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.