2009-08-31 9 views
50

Io lavoro su un metodo che fa qualcosa dato un parametro stringa. Un valore valido per il parametro stringa è diverso da null o string.Empty. Quindi il mio codice sembra così.Devo gettare ArgumentNullException se una stringa è vuota?

 
private void SomeMethod(string someArgument) 
{ 
    if(string.IsNullOrEmpty(someArgument)) 
     throw new ArgumentNullException("someArgument"); 

    // do some work 
} 

Niente di troppo eccitante. La mia domanda è, va bene lanciare un ArgumentNullException anche se la stringa è uguale a string.Empty? Perché tecnicamente non è nulla. Se ritieni che non dovrebbe gettare ArgumentNullException quale eccezione dovrebbe essere generata?

+1

Lanciare ArgumentNullException quando stringa "" è fuorviante. –

+0

Sono d'accordo, purtroppo la ragione per cui l'ho già fatto in questo modo è a causa della risposta che "Joe" ha dato, è usata così nel codice del framework .net. – Kepboy

risposta

35

ArgumentException deve essere generato per il caso String.Empty. Ciò indicherebbe un problema diverso da null. Per evitare un NullReferenceException prima ho verificato il null, quindi ho tagliato e verificato il caso vuoto per impedire il passaggio di spazi bianchi.

private void SomeMethod(string someArgument) 
{ 
    if(someArgument == null) 
     throw new ArgumentNullException("someArgument"); 

    if (someArgument.Trim() == String.Empty) 
     throw new ArgumentException("Input cannot be empty", "someArgument"); 

    // do some work 
} 

Come di .NET 4.0 è possibile utilizzare il metodo String.IsNullOrWhiteSpace per eseguire questi controlli in un colpo solo. In questo modo si rinuncia alla possibilità di specificare un tipo di eccezione granulare, quindi opterei per lo ArgumentException e aggiornerei il messaggio di conseguenza.

+0

Sto usando C# 2.0, l'unico riferimento a InvalidArgumentException è nello spazio dei nomi Microsoft.SqlServer.Management.Common, è ciò che raccomandi o stai suggerendo di creare la mia classe InvalidArgumentException? – Kepboy

+0

@ Keith: hai ragione, mio ​​errore. Puoi scrivere il tuo se sei così inclinato o usa l'ArgumentException fornito dal framework. Modificherò per riflettere il nome corretto. –

+3

Il costruttore ArgumentException non accetta un parametro "paramName" come ArgumentNullException. Quindi 'buttare nuova ArgumentException ("paramName")' è potenzialmente confuso, in quanto non fornisce alcuna indicazione su cosa c'è di sbagliato nell'argomento. Dovresti fornire un argomento "messaggio" come qualcosa ("someArgument potrebbe non essere una stringa vuota"). E in un'app internazionale questo messaggio dovrebbe essere localizzato. Quindi vorrei solo andare a tutto questo problema se c'è davvero bisogno di distinguere il caso nullo dal caso stringa vuota. – Joe

5

Si dovrebbe gettare un ArgumentException se una stringa vuota non è un input accettato per il metodo. Può essere molto confuso per i clienti se si lancia un ArgumentNullException mentre non hanno fornito un argomento null.

È semplicemente un altro caso d'uso. Potresti anche avere metodi che non accettano valori di input nulli ma che accettano stringhe vuote. È importante essere coerenti nell'intera applicazione.

+0

Stavo pensando alle linee di ArgumentOutOfRangeException ma forse è usato per le eccezioni degli intervalli di indice dell'array. – Kepboy

+0

Per le eccezioni dell'indice di array, viene utilizzata IndexOutOfRangeException. Dovresti utilizzare ArgumentOutOfRangeException solo se il tuo metodo è documentato per accettare solo una raccolta specifica di stringhe (ad es.: "abc", "def", "ghi" sono gli unici input accettati). –

+0

Grazie per il chiarimento. – Kepboy

1

ArgumentNullException viene talvolta utilizzato in .NET Framework per il caso String.IsNullOrEmpty - un esempio è System.Windows.Forms.Clipboard.SetText.

Quindi penso che sia ragionevole fare lo stesso nel codice, a meno che non ci sia un valore reale nel distinguere i due casi.

Si noti che questa e altre eccezioni derivate da ArgumentException indicano generalmente un errore di programmazione e pertanto devono fornire le informazioni necessarie per aiutare uno sviluppatore a diagnosticare il problema. Personalmente ritengo improbabile che uno sviluppatore possa trovarlo confuso se si utilizza ArgumentNullException per un argomento stringa vuoto, specialmente se si documenta questo comportamento come nell'esempio seguente.

+4

Non guarderei a Windows Forms per gli esempi delle ultime best practice nel codice di .NET Framework. Sono stato in grado di trovare rapidamente un esempio di contatore in File.Copy (stringa, stringa), che genera ArgumentNullException per null e ArgumentException per vuoto. – dcstraw

4

Considerando tutto ciò che è stato detto (Joe/Ahmad Mageed), avrei creato un'eccezione per quel caso.

class ArgumentNullOrEmptyException : ArgumentNullException 
+14

Non sarebbe meglio derivare da ArgumentException? In OOP, dire che "A o B" è una "A" non sembra giusto. – dcstraw

+0

@dcstraw ArgumentNullException deriva da ArgumentException. In questo caso penso che sia meglio ArgumentNullOrEmptyException derivare da ArgumentNullException. – Xtro

+0

Inoltre, penso che il suo nome dovrebbe essere StringArgumentNullOrEmptyException perché ha solo un significato per gli argomenti stringa. – Xtro

0

Questo dipende davvero dalle circostanze.

La domanda si riduce a, è davvero un errore? Con questo voglio dire che hai sempre un valore ? Se lo fai, allora probabilmente la soluzione migliore qui sta creando il proprio Exception, forse in questo modo:

class StringEmptyOrNullException : Exception 
{ 
} 

Dove si può anche aggiungere i propri costruttori e ha aggiunto informazioni ecc

Se, tuttavia, non è un "eccezionale" sta accadendo nel tuo programma, se fosse probabilmente un'idea migliore per restituire null dal metodo e gestirlo da lì.Basta ricordare, Exception sono per condizioni eccezionali.

Spero che questo aiuti,

Kyle

+1

Se * si * crea la propria eccezione, dovrebbe derivare da ArgumentException piuttosto che da Exception. – Joe

+0

A seconda del contesto, in questo contesto sì. Se vuoi usarlo in altri posti, lo rendi più generico. Ad esempio se hai un metodo che genera una stringa che non dovrebbe essere vuota, ArgumentException non sarà la scelta migliore. Quindi, in base alla quantità di utilizzo che hai a disposizione e al contesto in cui viene utilizzato, deciderete quindi da cosa ereditare. –

+0

IMO si tratta di due situazioni diverse: metodo che genera una stringa e un argomento passato in un metodo e preferirei avere due diversi tipi di eccezione. È meglio essere prolissi che inceppare più tipi di situazioni di errore in un'unica eccezione. –

0

Perché non utilizzare questo codice?

private void SomeMethod(string someArgument) 
{ 
//chek only NULL 
if(ReferenceEquals(someArgument,null)) 
    throw new ArgumentNullException("someArgument"); 

// and after trim and check 
if (someArgument.Trim() == String.Empty) 
    throw new ArgumentException("Input cannot be empty", "someArgument"); 

// do some work 
} 
Problemi correlati