Qual é a diferença entre levantar exceções e lançar exceções em Ruby?

StackOverflow https://stackoverflow.com/questions/51021

  •  09-06-2019
  •  | 
  •  

Pergunta

Ruby tem dois mecanismos de exceções diferentes:Lançar/Pegar e Levantar/Resgatar.

Por que temos dois?

Quando você deve usar um e não o outro?

Foi útil?

Solução

Eu penso http://hasno.info/ruby-gotchas-and-caveats tem uma explicação decente da diferença:

pegar/arremessar não é o mesmo que levantar/resgatar.catch/throw permite que você saia rapidamente dos blocos de volta a um ponto onde um catch é definido para um símbolo específico, raise Rescue é o verdadeiro tratamento de exceção que envolve o objeto Exception.

Outras dicas

  • raise, fail, rescue, e ensure lidar erros, também conhecido como exceções
  • throw e catch são controle de fluxo

Ao contrário de outros idiomas, o arremesso e a captura de Ruby não são usados ​​para exceções.Em vez disso, eles fornecem uma maneira de encerrar a execução cedo, quando não for necessário mais trabalho.(Grimm, 2011)

Terminar um único nível de fluxo de controle, como um while loop, pode ser feito com um simples return.Terminar muitos níveis de fluxo de controle, como um loop aninhado, pode ser feito com throw.

Embora o mecanismo de exceção de aumento e resgate seja ótimo para abandonar a execução quando as coisas dão errado, às vezes é bom poder saltar de alguma construção profundamente aninhada durante o processamento normal.É aqui que pegar e lançar é útil.(Thomas e Hunt, 2001)

Referências

  1. Grimm, Avdi."Jogue, pegue, levante, resgate ... estou tão confuso!" Blog de Rubylearning.Np, 11 de julho de 2011.Rede.1º de janeiro2012. http://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/.
  2. Thomas, Dave e Andrew Hunt."Programando Ruby." :O Guia do Programador Pragmático.Np, 2001.Rede.29 de setembro2015. http://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html.

https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise oferece uma excelente explicação que duvido que possa melhorar.Para resumir, vou pegando alguns exemplos de código da postagem do blog:

  1. raise/rescue são os análogos mais próximos do throw/catch construção com a qual você está familiarizado de outras linguagens (ou do Python raise/except).Se você encontrou uma condição de erro e gostaria throw sobre isso em outro idioma, você deve raise em Rubi.

  2. Rubi throw/catch permite interromper a execução e subir na pilha em busca de um catch (como raise/rescue faz), mas não se destina realmente a condições de erro.Deve ser usado raramente e existe apenas para quando "subir na pilha até encontrar um arquivo correspondente". catch"o comportamento faz sentido para um algoritmo que você está escrevendo, mas não faria sentido pensar no throw como correspondendo a uma condição de erro.

    Para que serve pegar e lançar em Ruby? oferece algumas sugestões sobre bons usos do throw/catch construir.

As diferenças comportamentais concretas entre eles incluem:

  • rescue Foo resgatará instâncias de Foo incluindo subclasses de Foo. catch(foo) só vai pegar o mesmo objeto, Foo.Não só você não pode passar catch um nome de classe para capturar instâncias dela, mas nem mesmo fará comparações de igualdade.Por exemplo

    catch("foo") do
      throw "foo"
    end
    

    lhe dará um UncaughtThrowError: uncaught throw "foo" (ou um ArgumentError em versões de Ruby anteriores a 2.2)

  • Várias cláusulas de resgate podem ser listadas...

    begin
      do_something_error_prone
    rescue AParticularKindOfError
      # Insert heroism here.
    rescue
      write_to_error_log
      raise
    end
    

    enquanto múltiplo catches precisam ser aninhados ...

    catch :foo do
      catch :bar do
        do_something_that_can_throw_foo_or_bar
      end
    end
    
  • Um nu rescue é equivalente a rescue StandardError e é uma construção idiomática.Um "nu catch", como catch() {throw :foo}, nunca pegará nada e não deve ser usado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top