Por que não as declarações que não fazem nada lançar uma exceção (ou avisar o desenvolvedor)?
-
21-09-2019 - |
Pergunta
Eu fui mordido um par de vezes por declarações em VB.NET (não sei se este efeito existe em C#) que parecem ser auto-referência, mas quando eles são executados, eles realmente não fazer nada, porque eles necessitam de um destino e um não é fornecida.Por exemplo:
Dim MyString as string = "String to test"
' Neither of these lines do anything '
MyString.Replace(" ", "-")
MyString.Substring(0,5)
' This will return the original string, because neither statement did anything '
Messagebox.Show(MyString)
Em ambos os casos, ele não parece se incomodar .NET que a declaração precisa de um alvo para atribuir o resultado, e eu não dou um.Há uma razão para que o IDE/compilador não avisar-me de esse efeito, ou que uma exceção "StatementDoesntDoAnything" não é jogado?Uma vez que o código é formada de tal maneira que ele nunca vai mudar nada, é claramente mal escrito.
Solução
Pode ser difícil dizer que ignorar o valor de retorno não se destina, pois algumas funções fazem algum efeito colateral e retornam um valor.
Funções que "apenas" os valores de retorno teriam que ser marcados como tal para que o compilador os verifique, e isso simplesmente não tem sido uma prioridade ou considerado um retorno suficiente sobre o investimento (obviamente, caso contrário, eles teriam feito :) .
Outras dicas
Sim, seria ótimo se métodos que não tivessem efeitos colaterais pudessem ser marcados com algum tipo de [NosideeffectSattribute ()] para que ferramentas como compiladores possam avisá-lo, mas atualmente não se sabe.
Mas você pode experimentar o FXCOP, ele pode identificar muitos erros de programação sutis nos conjuntos .NET.
Existem muitos casos em que os métodos retornam valores opcionalmente tratados pelo programador. Não há como o compilador saber que esse método em particular não faz nada. Pode ter um efeito colateral e o fato de você optar por não fazer nada com o valor de retorno do método deve ser uma decisão consciente de sua parte.
Se o compilador optar por avisá -lo de todas as instâncias que isso aconteceu, você receberá muitos avisos falsos.
Muitas vezes, é difícil para o compilador determinar se as funções "fazem alguma coisa". A menos que o compilador seja rigoroso Análise interprocedural (IPA), ele não pode determinar se a chamada de função tem um efeito colateral.
O IPA é um processo lento que aumenta significativamente os requisitos de memória dos compiladores, portanto, por padrão, a maioria dos compiladores não executa isso.
Este é o comportamento herdado de C, C ++ e foi feito orioginalmente para que você possa escolher se deve ou não usar o valor de retorno de uma função/método ... quando você escreve uma função/método que faz um monte de coisas e depois retorna algum valor, quando você chama, você tem a opção de escrever
variableName = functionName([parameterlist]);
Se você quiser usar o valor do retorno em algo, ou apenas
functionName([parameterlist]);
Se você não o fizer.
Para métodos de função que não têm efeitos colaterais (como os que você mencionam) como você observou, isso não faz sentido, mas alterá -lo para novos idiomas seria contado com a longa história de muitos outros idiomas que estão em conformidade com esse padrão ...
Eu não tenho certeza de ter ainda outra palavra-chave para obrigar ou não o valor de retorno para ser colocado em uma variável seria uma boa idéia para vários razão
1 ) Suponha que você adicionar uma palavra-chave quando o valor de retorno é opcional (daí o que implica geralmente é obrigatório) iria causar muita código para parar de compilar ou emitido toneladas de aviso
2) Suponha que você faça o inverso, a adição de uma palavra-chave quando o valor de retorno é forçado, algumas pessoas simplesmente usar variáveis dummy para armazená-los e continuar utilizando-os da forma ther usado para.
3) eu não acho que muitas pessoas que realmente tomar o tempo para ponderar sobre se ou não o valor de retorno é opcional ou não.Em alguns casos, eu tenho que admitir que é dado, mas não sempre.
Considere o método Dictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value)
: Ele verifica se a chave está no dicionário e, se for, coloca o valor no out
parâmetro. O valor de retorno é um bool
indicando se a operação foi bem -sucedida. Às vezes você se importa; Às vezes você não. Eu acho que essa é uma abordagem bastante aceita para métodos como esse; Se o compilador forçar você a atribuir o valor de retorno a uma variável, as pessoas teriam muito código como este:
int someValue = 0;
bool discard = IntDictionary.TryGetValue("key", out someValue);
// I don't even care if discard is true or false;
// someValue will be 0 if it wasn't in IntDictionary
Fui mordido algumas vezes por
tirando conclusões, não por
declarações em vb.net ... que ... na verdade não fazem nada
Mas isso está realmente muito bem documentado.