A volte finisco per dover scrivere un metodo o una proprietà per una libreria di classi per la quale non è eccezionale avere una risposta reale, ma un fallimento. Qualcosa non può essere determinato, non è disponibile, non è stato trovato, non è attualmente possibile o non ci sono più dati disponibili.
Penso che ci siano tre possibili soluzioni per una situazione relativamente non eccezionale per indicare un errore in C # 4:
- restituisce un valore magico che non ha altro significato (come
nulle-1); - genera un'eccezione (ad esempio
KeyNotFoundException); - restituisce
falsee fornisce il valore di ritorno effettivo in un parametroout, (ad esempioDictionary<,>.TryGetValue).
Quindi le domande sono: in quale situazione non eccezionale dovrei lanciare un'eccezione? E se non dovessi lanciare: quando restituisce un valore magico perferito sopra implementando un Try* metodo con un parametro out ? (Per me il parametro out sembra sporco, ed è più difficile utilizzarlo correttamente.)
Sto cercando risposte concrete, come le risposte che riguardano le linee guida di progettazione (non ne conosco i metodi Try* ), l'usabilità (come chiedo questo per una libreria di classi), l'uniformità con il BCL e la leggibilità .
Nella libreria di classi base di .NET Framework, vengono utilizzati tutti e tre i metodi:
- restituisce un valore magico che non ha altro significato:
-
Collection<T>.IndexOfrestituisce -1, -
StreamReader.Readrestituisce -1, -
Math.Sqrtrestituisce NaN, -
Hashtable.Itemrestituisce null;
-
- genera un'eccezione:
-
Dictionary<,>.Itemgenera KeyNotFoundException, -
Double.Parsegenera FormatException; o
-
- return
falsee fornisce il valore di ritorno effettivo in un parametroout:
Si noti che quando Hashtable è stato creato nel momento in cui non c'erano generici in C #, utilizza object e può quindi restituire null come valore magico. Ma con i generici, le eccezioni sono usate in Dictionary<,> e inizialmente non aveva TryGetValue . A quanto pare le intuizioni cambiano.
Ovviamente, il Item - TryGetValue e Parse - TryParse dualità è lì per un motivo, quindi presumo che lanciare eccezioni per errori non eccezionali sia in C # 4 non fatto . Tuttavia, i metodi Try* non sono sempre esistiti, anche se esisteva Dictionary<,>.Item .