Non sarò troppo contrario al primo approccio (restituendo null
), ma rinominerò il metodo per indicare chiaramente che potrebbe restituire null.
Firme come:
findCustomer(int customerId)
parse(string number)
pop(stack sequence)
non sono chiari. Se un cliente non esiste, il metodo restituisce null
o genera un'eccezione CustomerNotFound
? Se il numero è "abc" e non può essere ragionevolmente analizzato, il metodo restituisce null
o l'eccezione InvalidFormat
di lancio? Cosa succede quando pop
ing in un elemento da uno stack vuoto?
Invece:
findCustomerIfAny(int customerId)
tryParse(string number)
lastOrNull(stack sequence)
sono più facili da capire.
Altre opzioni che hai incluso:
1. out
parametri
Se la tua lingua supporta i parametri out
, un approccio diverso dovrebbe essere il seguente:
tryFindCustomer(int customerId, out customer result) returns bool
Il risultato booleano indica se il cliente è stato trovato o meno.
Personalmente, trovo questo approccio troppo prolisso e brutto. Non lo userò.
2. Tuple
Se la tua lingua ha delle tuple, puoi scrivere:
findCustomer(int customerId) returns (bool isFound, customer match)
Questo è perfettamente valido e potrebbe rendere il tuo codice estremamente esplicito.
3. Valore o impostazione predefinita
C'è anche un'altra interessante convenzione in LINQ in .NET. Un metodo che cerca il primo elemento di una sequenza, FirstOrDefault
, restituisce il valore predefinito se la sequenza è vuota.
Questo significa che:
[ 2, 7, 1 ].FirstOrDefault()
fornisce 2
, mentre:
[].FirstOrDefault()
indica 0
, poiché default(int)
è 0
. Nota che:
default(customer) ↔ null
default(System.Drawing.Point) ↔ System.Drawing.Point.Empty ↔ (0, 0)
ecc.
Purtroppo, non puoi eseguire l'override dell'operatore default
, il che rende questo approccio piuttosto limitato.
Non sono sicuro che questo ultimo approccio ti aiuterà nel tuo caso, ma vale la pena menzionarlo.
4. Stato all'interno del valore restituito
Un approccio personalizzato sarebbe quello di integrare un valore di stato all'interno della classe stessa. Ad esempio:
// 'findCustomer' always returns a non-null value.
selectedCustomer = findCustomer(customerIdFromInput)
// When the customer cannot be found, 'IsEmpty' is set to 'true'.
if (selectedCustomer.IsEmpty) {
throw CustomerNotFoundException;
}