Quando "Try" deveria ser usado nos nomes dos métodos C #?

180

Estávamos discutindo com nossos colegas de trabalho o que significa se o nome do método começa com "Try".

Havia as seguintes opiniões:

  • Use "Try" quando o método puder retornar um valor nulo.
  • Use "Try" quando o método não lançar uma exceção.

Qual é a definição oficial? O que "Try" diz no nome do método? Existe alguma diretriz oficial sobre isso?

ms007
fonte
83
+1 As pessoas que pensam tanto no nome de suas funções estão procurando "o próximo cara". Não sei por que isso está ficando perto de votos (e que está vindo de um cara que é lançado um monte deles esta noite.)
Jonathon Reinhart
7
@JonathonReinhart, obteve votos apertados porque "Como está atualmente, esta pergunta não se encaixa no nosso formato de perguntas e respostas. Esperamos que as respostas sejam apoiadas por fatos, referências ou conhecimentos específicos, mas essa pergunta provavelmente solicitará debate, argumentos , sondagens ou discussões prolongadas ".
Pranav Hosangadi
16
Não é uma declaração oficial pela Microsoft que responde à pergunta (ver minha resposta). Como isso não é um fato?
Erik Schierboom
6
@PranavHosangadi como Erik mencionou, é apoiado por fatos. Além disso, há muitos desenvolvedores de C # muito experientes que possuem conhecimentos específicos para fornecer uma resposta válida. Inferno, Eric Lippert é o principal arquiteto de linguagem C #. Eu acho que você pode chamar isso de conhecimento específico .
Jonathon Reinhart
4
@ErikSchierboom Essa é a orientação da MS é fato. Que a diretriz de MS é a diretriz correta a ser usada é subjetiva e discutível.
Servy

Respostas:

148

Isso é conhecido como padrão TryParse e foi documentado pela Microsoft. A página oficial do Exceções e Desempenho do MSDN diz :

Considere o padrão TryParse para membros que podem lançar exceções em cenários comuns para evitar problemas de desempenho relacionados a exceções.

Portanto, se você tiver um código para o qual um caso de uso regular significaria que poderia gerar uma exceção (como analisar um int), o padrão TryParse faz sentido.

Erik Schierboom
fonte
2
Outro link útil que os documentos desse padrão (procurar TryParse) blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
Vivek Maharajh
2
Basicamente, se você possui um método TryParse, deve ter um método Parse que lança quando o TryParse retornará false. Por outro lado, se você tem um método Parse, você deve considerar ter um método TryParse que falsa de retorno quando Parse jogaria
3Doubloons
5
+1. Apenas para acrescentar a isso, as exceções geralmente são para circunstâncias "excepcionais". Se você está fazendo algo que poderia facilmente falhar e que o fracasso não é particularmente notável, em seguida, usando esse padrão é mais idiomática que um try / catch
Adam Robinson
Esse padrão realmente exigia diretrizes da Microsoft? Parece coisas bastante básicas.
Dave Lawrence
19
Ele é coisas básicas, mas isso não significa que as orientações não são úteis. Consertar as coisas básicas pode ser bastante difícil se você não conhece a plataforma o suficiente.
Erik Schierboom
119

(Corrigido) Há diretrizes oficiais, como Erik sugeriu.

Quando vejo o TrySomethingmétodo, presumo que

  • não joga
  • retorna bool
  • se eu espero valor, ele é retornado via parâmetro 'out'
  • existe um Somethingmétodo que me permite lidar com qualquer exceção. (editar, sugerido por Jesse Webb)
não mostrar
fonte
4
Correção - Possui orientação oficial. Veja a resposta de Erik.
nothrow
8
+1 Mas também tenho uma quarta expectativa: se houver um TryFoométodo, haverá um Foométodo semelhante que me permitirá lidar com quaisquer `` exceções eu mesmo. As assinaturas desses métodos provavelmente serão diferentes, portanto seus usos não são intercambiáveis ​​sem outras alterações de código.
Jesse Webb
1
@ JesseWebb, obrigado por apontar isso. Adicionei seu comentário na minha resposta, se você não se importa.
nothrow
1
"Não joga" me parece generalizado demais. Por exemplo, Int32.TryParse (String, NumberStyles, IFormatProvider, Int32) lança ArgumentException se não gostar do parâmetro style.
Jirka Hanika #
Concordo que "não atira" poderia ser considerado generalizado demais, mas acredito que a intenção era transmitir que não atira como resultado da execução, e não como resultado do valor dos parâmetros.
precisa
8

Eu acho que você deve usar tryquando quiser prosseguir. Não importa que um método retorne algum valor ou não.

Caso 1: se retornar bem, você pode prosseguir de alguma maneira.

Caso 2: se não retornar: ainda está bom; você pode prosseguir de outra maneira.

E se você espera algum valor como saída desse método, use o outparâmetro

Exemplo

int value
if (dictionary.TryGetValue("key", out value))
{
    // Proceed in some way
}
else
{
    // Proceed in some other way
}
Ashok Damani
fonte
6

Você precisa usar "Try" no nome do método, quando quiser manifestar o fato de que a invocação do método pode produzir um resultado inválido. Seguindo o padrão .NET, a propósito, não é uma função que gera uma exceção, mas a função que retorna algum valor , VALIDou NON_VALIDdo ponto de vista do programa.

No final, trata-se de uma convenção de nomenclatura que você decide usar em seu grupo.

Tigran
fonte
5

Certifique-se de incluir tryno seu nome do método se:

  • você não lança nenhuma exceção
  • seu método tem a seguinte assinatura: bool TrySomething(input, out yourReturn)

Então, basicamente, se usarmos try-methods, apenas obteremos um resultado booleano.

Portanto, o código a seguir não lançará nenhuma exceção:

string input = "blabla";
int number;
if (int.TryParse(input, out number))
{
// wooohooo we got an int!
} else
{
//dooh!
}

Considerando que este código pode (e neste caso irá) lançar exceções:

string input = "blabla";
int number;
try
{
     number = int.Parse(input); //throws an exception
}
catch (Exception)
{
     //dooh!
}

Usar os métodos Try é uma maneira mais segura e defensiva de codificar. Além disso, o snippet de código nº 2 exige mais desempenho para ser executado se não for um número inteiro.

Fabian Bigler
fonte
Seu snippet de código nº 2 deve ser lido int number = int.Parse(input);se você quiser que seja mais significativo nesse contexto.
26613 Pierre Arnaud
@PierreArnaud Obrigado, mudou!
Fabian Bigler
Ainda falta a int number;declaração antes do bloco try e da number = ...atribuição.
Pierre Arnaud
@PierreArnaud Obrigado, eu também incluí 'int number' agora.
Fabian Bigler
Observe que você ainda pode lançar exceções se a exceção não estiver relacionada à ação direta que está sendo executada, como TryLoadFile(path, out file)woah, fora da RAM. Portanto, o responsável pela chamada não esperaria erros por um caminho ruim ou acesso negado, mas uma exceção para as coisas mais estranhas que também poderiam dar errado. E documente.
Luke Puplett
0

Tio Bob dá o exemplo abaixo em seu livro Clean Code . Sempre que esperamos que uma exceção seja lançada, podemos usar o Tryprefixo para o nome de um método:

public void sendShutDown()
{
    try{
        tryToShutDown();
    } catch (DeviceShutDownError e) {
        logger.log(e);            
    }
}

E então (adaptado):

private void tryToShutDown()
{
    //some code with no error handling, but
    //something might go wrong here
}

O tryToShutDownmétodo não faz nenhum tratamento de erros, porque essa é a responsabilidade do sendShutDownmétodo.

O TryParsepadrão da Microsoft viola a diretriz de código limpo que diz que devemos evitar os parâmetros de saída.

Se não estamos desenvolvendo uma nova versão do C #, não precisamos seguir todas as diretrizes da Microsoft. Às vezes eles não são os melhores.

Glauber
fonte