Melhor Prática: valor de retorno de função ou ByRef parâmetros de saída?
-
05-07-2019 - |
Pergunta
Eu tenho uma função chamada FindSpecificRowValue que leva em uma tabela de dados e retorna o número da linha que contém um valor particular. Se esse valor não for encontrado, quero indicar-lo para a função de chamada.
é a melhor abordagem para:
- Escreva uma função que retorna false se não for encontrado, verdade se encontraram, e o número da linha encontrado como um parâmetro byref / saída, ou
- Escreva uma função que retorna um inteiro e passar de volta -999 se o valor de linha não for encontrado, o número da linha se for?
Solução
Pessoalmente eu não faria tanto com esse nome método.
Eu sim fazer dois métodos:
TryFindSpecificRow
FindSpecificRow
Este seria seguir o padrão de Int32.Parse / TryParse, e em C # que poderia ser assim:
public static Boolean TryFindSpecificRow(DataTable table, out Int32 rowNumber)
{
if (row-can-be-found)
{
rowNumber = index-of-row-that-was-found;
return true;
}
else
{
rowNumber = 0; // this value will not be used anyway
return false;
}
}
public static Int32 FindSpecificRow(DataTable table)
{
Int32 rowNumber;
if (TryFindSpecificRow(table, out rowNumber))
return rowNumber;
else
throw new RowNotFoundException(String.Format("Row {0} was not found", rowNumber));
}
Editar:. alterado para ser mais apropriado para a questão
Outras dicas
funções que não deve lançar exceções.
Se o fracasso é parte do fluxo esperado em seguida, retornar um valor fora da faixa é OK, exceto onde você não pode pré-determinar o que um valor de out-of-band seria, caso em que você tem que lançar uma exceção.
Se eu tivesse que escolher entre suas opções eu iria escolher a opção 2, mas usar uma constante em vez de -999 ...
Você também pode definir valor de retorno como Nullable e regresso Nada se nada encontrado.
eu iria escolher a opção 2. Embora eu acho que eu iria usar apenas -1 não -999.
Richard Harrison é certo que uma constante chamada é melhor do que um nu -1 ou -999.
Eu iria com 2 ou alguma outra variação, onde o valor de retorno indica se o valor foi encontrado.
Parece que o valor da linha a função retorna (ou fornece uma referência a) já indica se o valor foi encontrado. Se um valor não foi encontrado, então parece não fazer sentido para fornecer um número de linha que não contém o valor, de modo que o valor de retorno deve ser -1, ou nulo, ou qualquer outro valor é adequado para a linguagem particular. Caso contrário, o fato de que um número de linha foi devolvido indica que o valor foi encontrado.
Assim, não parece ser uma necessidade de um valor de retorno separado para indicar se o valor foi encontrado. No entanto, tipo 1 pode ser apropriado se ele se encaixa com as expressões idiomáticas da língua particular, e as chamadas de função forma são realizadas na mesma.
Vá com 2), mas o retorno -1 (ou uma referência nula se devolver uma referência para a linha), essa expressão é usos extensivamente (incluindo por pelo .nets indexOf (rubrica) funções), é o que eu provavelmente faria .
BTW -1 é mais aceitável e largamente utilizado "número mágico" do que -999, isso é a única razão pela qual é "corrigir" (aspas usadas lá por uma razão).
Por mais que isso tem a ver com o que você espera. Caso o item esteja sempre lá, mas você simplesmente não sabe onde? Nesse caso retornar o índice normalmente, e lançar um erro / exceção se ele não está lá.
Neste caso, o item pode não estar lá, e isso é uma condição bem. É uma armadilha de erro para valores não selecionados em um GridView que se liga a uma tabela de dados.
Mais alguns possibilidades ainda não mencionado:
// Method 1: Supports covariance; can return default<T> on failure. T TryGetThing(ref bool success); // Method 2: Does not support covariance, but may allow cleaner code in some cases // where calling code would use some particular value in in case of failure. T TryGetThing(T DefaultValue); // Method 3: Does not support covariance, but may allow cleaner code in some cases // where calling code would use some particular value in case of failure, but should // not take the time to compute that value except when necessary. T TryGetThing(Func<T> AlternateGetMethod); // Method 4: Does support covariance; ErrorMethod can throw if that's what should // happen, or it can set some flag which is visible to the caller in some other way. T TryGetThing(Action ErrorMethod);
A primeira abordagem é o inverso do método Microsoft desenvolveu nos dias antes do suporte existia para interfaces covariantes. A última é, em alguns aspectos, o mais versátil, mas é provável que requerem a criação de um par de instâncias de objeto novo GC (fechamento por exemplo, um e um delegado) cada vez que for usado.