Recentemente, comecei a programar em Ruby e estou olhando para o tratamento de exceções.
Eu queria saber se ensure
era o equivalente Ruby finally
em c #? Eu deveria ter:
file = File.open("myFile.txt", "w")
begin
file << "#{content} \n"
rescue
#handle the error here
ensure
file.close unless file.nil?
end
ou devo fazer isso?
#store the file
file = File.open("myFile.txt", "w")
begin
file << "#{content} \n"
file.close
rescue
#handle the error here
ensure
file.close unless file.nil?
end
É ensure
chamado, não importa como, mesmo que uma exceção não seja levantada?
ruby-on-rails
ruby
exception
exception-handling
error-handling
Lloyd Powell
fonte
fonte
begin
bloco.Respostas:
Sim,
ensure
garante que o código seja sempre avaliado. É por isso que é chamadoensure
. Portanto, é equivalente a Java e C # 'sfinally
.O fluxo geral de
begin
/rescue
/else
/ensure
/end
é assim:Você pode deixar de fora
rescue
,ensure
ouelse
. Você também pode deixar de fora as variáveis e, nesse caso, não poderá inspecionar a exceção no seu código de manipulação de exceções. (Bem, você sempre pode usar a variável de exceção global para acessar a última exceção que foi gerada, mas isso é um pouco hacky.) E você pode deixar de fora a classe de exceção. Nesse caso, todas as exceções herdadasStandardError
serão capturadas. (Por favor note que este não significa que todas as exceções são capturadas, porque há exceções que são instâncias deException
, mas nãoStandardError
. Exceções Principalmente muito graves que comprometem a integridade do programa, comoSystemStackError
,NoMemoryError
,SecurityError
,NotImplementedError
,LoadError
,SyntaxError
,ScriptError
,Interrupt
,SignalException
ouSystemExit
.)Alguns blocos formam blocos de exceção implícitos. Por exemplo, definições de método são implicitamente também blocos de exceção, portanto, em vez de escrever
você escreve apenas
ou
O mesmo se aplica às
class
definições emodule
definições.No entanto, no caso específico que você está perguntando, existe realmente um idioma muito melhor. Em geral, quando você trabalha com algum recurso que precisa limpar no final, faz isso passando um bloco para um método que faz toda a limpeza para você. É semelhante a um
using
bloco em C #, exceto que Ruby é realmente poderoso o suficiente para que você não precise esperar que os sumos sacerdotes da Microsoft desçam da montanha e graciosamente alterem seu compilador para você. No Ruby, você pode simplesmente implementá-lo:E o que você sabe: isso já está disponível na biblioteca principal como
File.open
. Mas é um padrão geral que você também pode usar em seu próprio código, para implementar qualquer tipo de limpeza de recurso (à lausing
em C #) ou transações ou qualquer outra coisa que você possa imaginar.O único caso em que isso não funciona, se a aquisição e a liberação do recurso forem distribuídas por diferentes partes do programa. Mas se estiver localizado, como no seu exemplo, você poderá usar facilmente esses blocos de recursos.
BTW: no C # moderno,
using
é realmente supérfluo, porque você pode implementar os blocos de recursos no estilo Ruby:fonte
ensure
instruções sejam executadas por último, elas não são o valor de retorno.ensure
é chamado, não importa o quê."Para sua informação, mesmo que uma exceção seja levantada novamente na
rescue
seção, oensure
bloco será executado antes que a execução do código continue no próximo manipulador de exceções. Por exemplo:fonte
Se você deseja garantir que um arquivo seja fechado, use o formato de bloco de
File.open
:fonte
Sim,
ensure
é chamado em qualquer circunstância. Para obter mais informações, consulte " Exceções, capturas e lançamentos " do livro Ruby de programação e procure por "garantir".fonte
Sim,
ensure
ASSEGURA que seja executado sempre, para que você não precisefile.close
dobegin
bloco.A propósito, uma boa maneira de testar é fazer:
Você pode testar para ver se "========= dentro garantir bloco" será impresso quando houver uma exceção. Em seguida, você pode comentar a instrução que gera o erro e verificar se a
ensure
instrução é executada, verificando se alguma coisa é impressa.fonte
É por isso que precisamos
ensure
:fonte
Sim,
ensure
comofinally
garantias de que o bloco será executado . Isso é muito útil para garantir a proteção de recursos críticos, como fechar um identificador de arquivo por erro ou liberar um mutex.fonte
File.open
parte NÃO está dentro do bloco de garantia inicial. Sófile.close
é, mas não é suficiente.