2009-09-22 17 views
8

C'è qualche differenza comportamentale tra:throw new Exception vs blocco Catch

if (s == null) // s is a string 
{ 
throw new NullReferenceException(); 
} 

E:

try 
{ 
    Console.Writeline(s); 
} 


catch (NullReferenceException Ex) 
{ // logic in here 
} 

Entrambi generano eccezioni di oggetto null, se s è nullo. Il primo esempio è più leggibile in quanto mostra esattamente dove si verifica l'errore (il bit di eccezione si trova proprio accanto alla linea che causerà l'eccezione).

Ho visto questo stile di codifica molto su vari blog da vari programmatori di tutti i tipi di livelli di abilità, ma perché non eseguire solo la logica principale controllando se s non è nullo e quindi salvare l'eccezione da essere mai sollevato? C'è un lato negativo di questo approccio?

Grazie

+1

+1 Buona domanda –

risposta

18

No, Console.WriteLine(null) non un'eccezione. Non stamperà nulla. Ora supponendo che tu intenda qualcosa del tipo:

Console.WriteLine(s.Length); 

allora ha senso ... e dovresti usare il primo modulo. Dovrebbero verificarsi delle eccezioni quando non è possibile prevederle in anticipo con le informazioni correnti. Se riesci facilmente a capire che qualcosa non funziona, non ha senso provare un'operazione che è destinata a fallire. Porta a un codice che è più difficile da capire e peggiora.

Quindi NullReferenceException, ArgumentNullException e simili non dovrebbero essere catturati a meno che non siano dovuti a un nasty API which sometimes throws exceptions which you can handle, but which shouldn't really be being thrown in the first place. Questo è il motivo per cui nei Contratti di codice, il comportamento predefinito per un contratto fallito è di generare un'eccezione che non è possibile intercettare , oltre a rilevare lo tutto (che di solito è in cima alla pila).

+0

Grazie. Intendevo ogni caso in cui la variabile viene utilizzata (in un metodo/ctor) ma causa una NullReferenceException o un riferimento a un oggetto non impostato su un'istanza di un errore dell'oggetto. Una cosa che mi è stato detto da un amico che codifica è che il primo modulo dovrebbe essere usato dove l'eccezione verrà catturata dal chiamante? Quindi, se ho un altro metodo che chiama il primo modulo e ha un blocco catch per la linea di eccezioni generata. Sei d'accordo con questo? – dotnetdev

+0

Che cosa è, se esiste, la relazione tra il riferimento all'oggetto non impostato su un'istanza di un oggetto e NRE? – dotnetdev

+0

Come fai a sapere se l'eccezione verrà catturata dal chiamante? E qual è la differenza tra lanciare esplicitamente un'eccezione quando qualcosa andrà storto (che è molto più informativo) e lasciare che il framework .NET lanci un'eccezione NullRef generica? –

2

Come già detto da Jon Skeet, Console.WriteLine (null) non genererà un'eccezione.

Accanto a questo, vorrei dire che dovresti "fallire velocemente". Ciò significa che devi inserire clausole di 'guardia' nei tuoi metodi e controllare gli argomenti che sono stati dati nei tuoi metodi se possono essere considerati validi. Ciò consente di generare un'eccezione autonomamente e di fornire un messaggio aggiuntivo che sarà utile durante il debug. Il messaggio può dare un'indicazione chiara su cosa non ha funzionato, e questo è molto più pratico se ci si trova di fronte a una NullReferenceException che è stata lanciata senza alcuna buona informazione nella sua proprietà message.

0

Se stai seguendo un approccio di tipo Design by Contract alle cose, una parte di codice può specificare che genera eccezioni per specificare il suo contratto e rafforzarlo. L'altra metà è, naturalmente, chiamando il codice riconoscendo il contratto e rispettandolo.

In questo caso significherebbe che se si conosce un metodo verrà generata un'eccezione se si passa in null (vale a dire il suo contratto è che non si passano null), quindi è necessario controllare prima di chiamarlo.

Jon Skeet dice che il metodo non genererà comunque un'eccezione. Questo può o non può essere vero, ma il principio di salvaguardare per i contratti di metodo (che credo fosse il punto della tua domanda).

1

Se si sta scrivendo una libreria di classi possono esserci occasioni in cui si sa che se un determinato parametro contiene un valore nullo, ciò potrebbe causare problemi lungo la linea.In questi casi, di solito trovo che sia una buona idea lanciare un'eccezione (anche se probabilmente utilizzerei lo ArgumentNullException per quel caso) per rendere l'utente della libreria di classi consapevole di ciò nel modo più rapido e chiaro possibile.

Le eccezioni non sono sempre una cosa negativa.

1

Jon Skeet ha ragione ma, più in generale, è tutta una questione di semantica.

Se la situazione ha qualche significato applicativo (numero fuori limite, data di nascita in futuro, ecc.), Potresti volerlo testare prima di fare qualsiasi operazione e lanciare un'eccezione personalizzata (che è uno con significato per il tuo applicazione).

Se la situazione è veramente "eccezionale", è sufficiente scrivere il codice come se il valore indicato fosse corretto. Vedi, se metti il ​​test, lo farai ogni volta, sapendo che la VM lo farà comunque nel caso in cui debba lanciare un'eccezione. Dal punto di vista delle prestazioni, se l'errore si verifica con un evento statisticamente piccolo, non ha senso.

Problemi correlati