Best practice: valore di ritorno della funzione o parametri di output byref?
-
05-07-2019 - |
Domanda
Ho una funzione chiamata FindSpecificRowValue che accetta un datatable e restituisce il numero di riga che contiene un valore particolare. Se quel valore non viene trovato, desidero indicarlo alla funzione chiamante.
È l'approccio migliore per:
- Scrivi una funzione che restituisce false se non trovato, true se trovato e il numero di riga trovato come parametro byref / output o
- Scrivi una funzione che restituisce un int e ritorna indietro -999 se il valore della riga non viene trovato, il numero della riga se lo è?
Soluzione
Personalmente non lo farei nemmeno con quel nome di metodo.
Vorrei invece fare due metodi:
TryFindSpecificRow
FindSpecificRow
Questo seguirebbe il modello di Int32.Parse / TryParse e in C # potrebbero apparire così:
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));
}
Modifica: modificato per essere più appropriato alla domanda.
Altri suggerimenti
??che falliscono dovrebbero generare eccezioni.
Se l'errore fa parte del flusso previsto, la restituzione di un valore fuori banda è OK, tranne nei casi in cui non è possibile determinare in anticipo quale valore fuori banda sarebbe, nel qual caso è necessario generare un'eccezione.
Se dovessi scegliere tra le tue opzioni sceglierei l'opzione 2, ma utilizzerei una costante anziché -999 ...
Puoi anche definire il valore di ritorno come Nullable e return Nothing se non viene trovato nulla.
Sceglierei l'opzione 2. Anche se penso che userei solo -1 non -999.
Richard Harrison ha ragione nel dire che una costante nominata è meglio di una -1 o -999 nuda.
Vorrei andare con 2, o qualche altra variante in cui il valore restituito indica se il valore è stato trovato.
Sembra che il valore della riga restituita dalla funzione (o che fornisce un riferimento) indichi già se il valore è stato trovato. Se non è stato trovato un valore, non ha senso fornire un numero di riga che non contenga il valore, quindi il valore restituito dovrebbe essere -1 o Null o qualsiasi altro valore adatto per la lingua specifica. In caso contrario, il fatto che sia stato restituito un numero di riga indica che il valore è stato trovato.
Pertanto, non sembra essere necessario un valore di ritorno separato per indicare se il valore è stato trovato. Tuttavia, il tipo 1 potrebbe essere appropriato se si adatta agli idiomi di una determinata lingua e al modo in cui vengono eseguite le chiamate di funzione.
Vai con 2) ma restituisci -1 (o un riferimento null se restituisci un riferimento alla riga), che il linguaggio è ampiamente utilizzato (incluso da .nets indexOf (item) funzioni), è quello che probabilmente farei .
BTW -1 è più accettabile e ampiamente usato "numero magico" di -999, questo è l'unico motivo per cui è "corretto" (virgolette utilizzate lì per un motivo).
Comunque gran parte di questo ha a che fare con quello che ti aspetti. L'articolo dovrebbe essere sempre lì, ma non sai dove? In tal caso, restituisci l'indice normalmente e genera un errore / un'eccezione se non è presente.
In questo caso, l'articolo potrebbe non essere presente e questa è una condizione accettabile. È una trappola per errori per valori non selezionati in un GridView che si lega a un datatable.
Altre possibilità non ancora menzionate:
// 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);
Il primo approccio è il contrario del metodo sviluppato da Microsoft nei giorni precedenti l'esistenza del supporto per le interfacce covarianti. L'ultimo è in qualche modo il più versatile, ma probabilmente richiederà la creazione di un paio di nuove istanze di oggetti GC (ad esempio una chiusura e un delegato) ogni volta che viene utilizzato.