Eu gosto de usar: ArgumentException
, ArgumentNullException
, e ArgumentOutOfRangeException
.
Também há outras opções que não se concentram tanto no argumento em si, mas julgam a chamada como um todo:
InvalidOperationException
- O argumento pode estar OK, mas não no estado atual do objeto. O crédito vai para o STW (anteriormente Yoooder). Vote sua resposta também.
NotSupportedException
- Os argumentos transmitidos são válidos, mas simplesmente não são suportados nesta implementação. Imagine um cliente FTP e você passa um comando no qual o cliente não suporta.
O truque é lançar a exceção que melhor expressa por que o método não pode ser chamado do jeito que é. Idealmente, a exceção deve ser detalhada sobre o que deu errado, por que está errado e como corrigi-lo.
Adoro quando as mensagens de erro apontam para ajuda, documentação ou outros recursos. Por exemplo, a Microsoft deu um bom primeiro passo com seus artigos da Base de Dados de Conhecimento, por exemplo, “Por que recebo uma mensagem de erro" Operação interrompida "quando visito uma página da Web no Internet Explorer?” . Quando você encontra o erro, eles apontam para o artigo da KB na mensagem de erro. O que eles não fazem bem é que não dizem a você, por que especificamente falhou.
Obrigado a STW (ex Yoooder) novamente pelos comentários.
Em resposta ao seu acompanhamento, eu jogaria um ArgumentOutOfRangeException
. Veja o que o MSDN diz sobre essa exceção:
ArgumentOutOfRangeException
é lançado quando um método é chamado e pelo menos um dos argumentos passados para o método não é referência nula ( Nothing
no Visual Basic) e não contém um valor válido.
Portanto, nesse caso, você está passando um valor, mas esse não é um valor válido, pois seu intervalo é de 1 a 12. No entanto, a maneira como você documenta isso deixa claro o que sua API lança. Porque, embora eu possa dizer ArgumentOutOfRangeException
, outro desenvolvedor pode dizer ArgumentException
. Facilite e documente o comportamento.
FormatException
: a exceção lançada quando o formato de um argumento é inválido ou quando uma sequência de formato composto não está bem formada.Votei na resposta de Josh , mas gostaria de adicionar mais uma à lista:
System.InvalidOperationException deve ser lançado se o argumento for válido, mas o objeto estiver em um estado em que o argumento não deve ser usado.
Atualização obtida do MSDN:
Digamos que seu objeto tenha um método PerformAction (ação enmSomeAction), enmSomeActions válidas são Open e Close. Se você chamar PerformAction (enmSomeAction.Open) duas vezes seguidas, a segunda chamada lançará InvalidOperationException (uma vez que o artigo era válido, mas não para o estado atual do controle)
Como você já está fazendo a coisa certa ao programar defensivamente, tenho uma outra exceção a ser mencionada: ObjectDisposedException. Se seu objeto implementa IDisposable, você deve sempre ter uma variável de classe rastreando o estado disposto; se seu objeto foi descartado e um método é chamado, você deve aumentar o ObjectDisposedException:
Atualização: Para responder ao seu acompanhamento: É uma situação um pouco ambígua e é um pouco mais complicada por um tipo de dados genérico (não no sentido do .NET Generics) sendo usado para representar um conjunto específico de dados; um enum ou outro objeto fortemente tipado seria um ajuste mais ideal - mas nem sempre temos esse controle.
Pessoalmente, eu me inclinaria para o ArgumentOutOfRangeException e forneceria uma mensagem indicando que os valores válidos são 1-12. Meu raciocínio é que, quando você fala sobre meses, assumindo que todas as representações inteiras de meses são válidas, você espera um valor no intervalo de 1 a 12. Se apenas alguns meses (como meses com 31 dias) fossem válidos, você não estaria lidando com um intervalo per se e eu lançaria uma ArgumentException genérica que indicava os valores válidos, e também os documentaria nos comentários do método.
fonte
Dependendo do valor real e qual exceção se encaixa melhor:
ArgumentException
(algo está errado com o valor)ArgumentNullException
(o argumento é nulo enquanto isso não é permitido)ArgumentOutOfRangeException
(o argumento tem um valor fora do intervalo válido)Se isso não for preciso, basta derivar sua própria classe de exceção
ArgumentException
.A resposta de Yoooder me iluminou. Uma entrada é inválida se não for válida a qualquer momento, enquanto uma entrada é inesperada se não for válida para o estado atual do sistema. Portanto, no caso posterior, a
InvalidOperationException
é uma escolha razoável.fonte
exceção de argumento.
fonte
ArgumentException :
Também existem algumas subclasses para tipos específicos de invalidez. O link possui resumos dos subtipos e quando eles devem ser aplicados.
fonte
Resposta curta:
nem
Resposta mais longa:
usar Argumento * A exceção (exceto em uma biblioteca que é um produto, como a biblioteca de componentes) é um cheiro. As exceções são para lidar com situações excepcionais, não com bugs e com deficiências do usuário (ou seja, consumidor da API).
Resposta mais longa:
Lançar exceções para argumentos inválidos é rude, a menos que você escreva uma biblioteca.
Prefiro usar asserções, por dois (ou mais) motivos:
Aqui está como é o tratamento da exceção nula (sendo sarcástico, obviamente):
Exceções devem ser usadas quando a situação é esperada, mas excepcional (acontecem coisas que estão fora do controle do consumidor, como falha de E / S). Argumento * Exceção é uma indicação de um bug e deve (na minha opinião) ser tratado com testes e assistido com Debug.Assert
BTW: Nesse caso específico, você poderia ter usado o tipo Month, em vez de int. O C # fica aquém quando se trata de digitar safety (Aspect # rulez!), Mas às vezes você pode impedir (ou capturar em tempo de compilação) esses erros todos juntos.
E sim, a MicroSoft está errada sobre isso.
fonte
Existe uma ArgumentException padrão que você pode usar ou pode criar uma subclasse e criar a sua própria. Existem várias classes ArgumentException específicas:
http://msdn.microsoft.com/en-us/library/system.argumentexception(VS.71).aspx
Qualquer um que funcione melhor.
fonte