Questão 1:
É por causa do retorno novo StreamReader (nome do arquivo); dentro do loop for? ou o fato de você não precisar de um loop for nesse caso?
O leitor de stream não tem nada a ver com isso. O anti-padrão surge devido a um claro conflito de intenção entre o foreach
e o if
:
Qual é o propósito do foreach
?
Suponho que sua resposta será algo como: "Quero executar repetidamente um determinado pedaço de código"
Quantos arquivos você espera processar?
Como você pode ter apenas um nome de arquivo específico (incluindo extensão) em uma pasta específica, isso prova que seu código pretende encontrar um arquivo aplicável.
Isso também é confirmado pelo fato de você estar retornando um valor imediatamente. Na verdade, você não se importa com uma segunda partida, mesmo que ela exista.
Há situações em que isso não é um anti-padrão.
- Se você também procurar nos subdiretórios (
Directory.GetFiles(".", SearchOption.AllDirectories)
), é possível encontrar mais de um arquivo com o mesmo nome de arquivo (incluindo extensão)
- Se você procurar correspondências parciais de nome de arquivo (por exemplo, todo arquivo cujo nome começa com
"Test_"
, ou todo "*.zip"
arquivo.
Observe que esses dois casos exigiriam que você processasse várias correspondências e, portanto, não retornasse um valor imediatamente.
Questão 2:
Para corrigir o segundo exemplo, você o reescreveria sem a instrução if e, em vez disso, cercaria o StreamReader com um bloco try-catch e, se ele gerar uma FileNotFoundException, você o manipulará no bloco catch adequadamente.
Exceções são caras. Eles nunca devem ser usados no lugar da lógica de fluxo adequada. Exceções são, como o nome sugere circunstâncias excepcionais .
Por esse motivo, você não deve remover o if
.
Conforme esta resposta no SoftwareEngineering.SE :
Geralmente, o uso de exceções para o fluxo de controle é um antipadrão, com exceções notáveis da tosse específica da situação e do idioma.
Como um resumo rápido do motivo, geralmente, é um antipadrão:
- Exceções são, em essência, sofisticadas declarações GOTO
- Programar com exceções, portanto, leva a mais difícil leitura e compreensão do código
- A maioria dos idiomas possui estruturas de controle existentes projetadas para resolver seus problemas sem o uso de exceções
- Os argumentos de eficiência tendem a ser discutíveis para os compiladores modernos, que tendem a otimizar com a suposição de que as exceções não são usadas para o fluxo de controle.
Leia a discussão no wiki de Ward para obter informações muito mais detalhadas.
Se você precisa agrupar isso em uma tentativa / captura, depende muito da sua situação:
- Qual a probabilidade de você encontrar uma condição de corrida?
- Você é realmente capaz de lidar com essa situação ou deseja que esse problema borbulhe para o usuário porque não sabe como lidar com isso?
Nada é sempre uma questão de "sempre usá-lo". Para provar meu argumento:
Estudos separados comprovaram que você tem menos chances de se machucar ao usar capacete, óculos de proteção e coletes à prova de balas.
Então, por que não estamos todos usando esse equipamento de segurança o tempo todo?
A resposta simples é que existem desvantagens em usá-las:
- Custa dinheiro
- Isso torna seu movimento mais pesado
- Pode ser bastante quente para usá-lo.
Agora estamos chegando a algum lugar: existem prós e contras . Em outras palavras, só faz sentido usar este equipamento nos casos em que os profissionais superam os contras.
- É muito mais provável que os trabalhadores da construção sofram ferimentos durante o trabalho. Eles se beneficiam de um capacete de segurança.
- Os funcionários de escritório, por outro lado, têm uma chance muito menor de se machucar. Capacetes de segurança não valem a pena.
- Um membro da equipe da SWAT tem muito mais chances de levar um tiro, comparado a um trabalhador de escritório.
Você deve encerrar a chamada em uma tentativa / captura? Isso depende muito se os benefícios de fazê-lo superam o custo de sua implementação.
Observe que outros podem argumentar que são necessárias apenas algumas teclas para envolvê-lo, portanto, obviamente, isso deve ser feito. Mas esse não é o argumento inteiro:
- Você precisa decidir o que fazer depois de capturar a exceção.
- Se houver muitas chamadas diferentes para arquivos diferentes em toda a base de código, a decisão de agrupar uma em uma tentativa / captura geralmente significa que você precisará agrupar todos esses casos. Isso pode ter um efeito dramático na quantidade de esforço necessária para implementá-lo.
- É perfeitamente possível que você intencionalmente queira não lidar com uma exceção.
- Observe que seu aplicativo precisará manipular a exceção em algum momento, mas isso não é necessariamente imediatamente após a exceção ter sido gerada.
Então a escolha é sua. Existe algum benefício em fazer isso? Você acha que isso melhora o aplicativo, mais do que o esforço para custear sua implementação?
Atualização - De um comentário que escrevi para a outra resposta, pois acho que é uma consideração relevante para você também:
Depende muito do contexto circundante.
- Se a abertura do leitor de fluxo for precedida por
if(!File.Exists) File.Create()
, a ausência do arquivo ao abrir o leitor de fluxo é realmente excepcional .
- Se o nome do arquivo foi selecionado em uma lista de arquivos existentes, sua repentina ausência é novamente excepcional .
- Se você estiver trabalhando com uma sequência que ainda não testou no diretório; a ausência do arquivo é um resultado perfeitamente lógico e, portanto, não excepcional .