2012-06-22 14 views
7

Ho una classe contenente una raccolta di elementi. Per comodità ho fornito GetCurrentItem che viene realizzato tramiteCreazione di una proprietà che può generare IndexOutOfRangeException

public Type GetCurrentItem 
{ 
    get { return this.items[this.items.Count - 1]; } 
} 

che sarà un'eccezione se non ci sono elementi nella lista.

Devo far scattare l'eccezione o devo restituire null? Se questa fosse una API che ti ho consegnato, cosa ti aspetti? L'eccezione o null? C'è un modo migliore per gestire questo?

+2

Qual è l'API corretto: 'Enumerable.Single' o' Enumerable.SingleOrDefault'? (risposta: dipende) –

risposta

9

Per quanto è più corretto? Come suggerisce il commento di Kirk: dipende. A volte un null ha senso logico ea volte un'eccezione è più adatta se nessun valore predefinito è ragionevole. Una cosa che provo a fare è pensare "sta chiamando GetCurrentItem un errore logico o una cosa sicura?"

Se non è possibile chiamare GetCurrentItem quando non ce ne sono, lanciare un'eccezione è la rotta corretta. Ad esempio, se la tua raccolta ha una proprietà HasCurrent o IsEmpty in cui qualcuno potrebbe esaminare il risultato prima di chiamare GetCurrentItem, allora dovrebbe "conoscere meglio". Ma se l'elemento corrente è null è un modo logico corretto di utilizzare la classe, quindi progettarlo in quel modo. In entrambi i casi, documenterei il comportamento nei commenti di codice per consentire agli utenti di conoscere il comportamento previsto.

Lo dirò comunque, esponendo l'eccezione ArgumentOutOfRange potrebbero verificarsi errori di implementazione. Cioè, se l'utente di questa classe non ha idea che la struttura interna sia una matrice o List<T>, allora non escludere quell'eccezione, ma catturarla, avvolgerla e lanciarne una più significativa (personalizzato, o qualcosa di simile InvalidOperationException).

Dal momento che non stanno passando davvero direttamente in un argomento, inducendole un'eccezione ArgumentOutOfRange potrebbe essere fonte di confusione :-)

+0

Una buona scelta di eccezione è 'InvalidOperationException', seguendo l'esempio impostato da' Stack .Peek() '. –

+0

@ MichaelLiu: Sì, d'accordo. Lo stavo aggiungendo nella mia modifica proprio come hai commentato :-) –

3

Lasciare un errore. Questo è esattamente come funzionano le altre collezioni. Dovrebbe essere compito dell'applicazione utente gestire le potenziali eccezioni (specialmente quando si lavora con le raccolte). Potrebbe esserci un metodo bool HasSelection() che l'utente può chiamare prima di procedere.

3

Le eccezioni devono essere utilizzate per casi eccezionali. Se CurrentItem può essere nullo, non si deve generare un'eccezione. Non vedo perché non avere un CurrentItem è eccezionale.

1

La domanda allora è se ci si aspetta GetCurrentItem per restituire un valore di sicurezza. Se Type è annullabile, GetCurrentItem dovrebbe probabilmente restituire null quando non c'è alcun elemento corrente. Se ti aspetti sempre che l'elenco sia non vuoto e che ci sia sempre qualcosa selezionato per impostazione predefinita, genera un'eccezione significativa.

Generalmente non si dovrebbe generare un'eccezione a meno che il proprio caso non sia un'eccezione e non un normale caso d'uso. Tuttavia, questo può essere piuttosto soggettivo.

0

Se questo GetCurrentItem ha senso per la tua API, genererei "InvalidOperationException" quando non ci sono articoli. Si consiglia di nominarlo diversamente se si consente null come risultato valido.

Considerare se il metodo esistente LINQ Last fornisce già la stessa funzionalità.

1

Provo a pensarci dal punto di vista dell'utente. Vai per lo Principal of Least Astonishment.

Se stavo usando la libreria o l'oggetto e ho chiamato GetCurrentItem e uno IndexOutOfRangeException è stato lanciato, penserei: "Non ho chiamato nulla con un indice, volevo l'elemento corrente". Pertanto, il mio suggerimento sarebbe di restituire null, il che mi farebbe pensare: "Oh, non c'è nessun elemento attuale".

In alternativa, se la proprietà fosse un indicizzatore e volevo ottenere un elemento in un determinato indice, non sarei sorpreso da un IndexOutOfRangeException.

Problemi correlati