2014-07-09 10 views
5

Si consideri la seguente classe e il metodo:Quale eccezione nulla da lanciare?

public class MyDto 
{ 
    public MyDtoChild Child {get; set;} 
} 

e

public void ProcessDto(MyDto myDto) 
{ 
    if(myDto == null) throw new ArgumentNullException("myDto"); 
    this.CheckSomething(myDto.Child.ChildProperty); 
} 

Se chiamato con un MyDto con un null Child sinistra per esso è di possedere dispositivi di questo lancerà una NullReferenceException che può essere estremamente difficile da diagnosticare in metodi più complessi.

In genere lancio un ArgumentNullException all'inizio del metodo se myDto è nullo ma qual è l'eccezione appropriata da lanciare se myDto.Children è nullo? Un ArgumentNullException? A NullReferenceException? Un'eccezione personalizzata?

+0

È possibile garantire che 'MyDto.Child' non sarà mai null utilizzando un modificatore' readonly' sul proprio campo di supporto, assumendo che 'MyDto' possieda il valore del campo. – Dai

+0

@KamilT semplicemente perché mi ci sono volute diverse ore per rintracciare dove questo particolare ref null sta arrivando e mi piacerebbe renderlo più robusto per i futuri sviluppatori. – Liath

+0

Va bene che il figlio sia "nullo" in altre parti del sistema o sia un caso eccezionale? –

risposta

5

Come indicato dalle risposte precedenti, non dovrebbe essere un ArgumentNullException poiché l'argomento myDTO non è NULL. Per me ha più senso lanciare un ArgumentException poiché l'argomento passato al metodo non ha soddisfatto i requisiti (ci si aspetta che i figli non siano nulli). Inoltre, la situazione si inserisce la descrizione del ArgumentException:

ArgumentException viene generata quando un metodo viene richiamato e almeno una degli argomenti passati non soddisfa la specifica del parametro del del metodo chiamato.

+0

Grazie a tutti coloro che hanno dato suggerimenti. La seleziono come risposta in quanto conferma il commento di @Silvermind riguardo al non aumentare i ref null e fornisce un buon livello di descrizione del perché. – Liath

3

Figlio del tuo argomento non è il tuo argomento, quindi ArgumentNullException non è appropriato qui. Penso che il modo migliore sarà quello di lanciare NullReferenceException con un messaggio di spiegazione.

+3

Non aumentare [tipi di eccezioni riservate] (http://msdn.microsoft.com/en-us/library/ms182338.aspx) come 'NullReferenceException'. Usa 'InvalidOperationException' con un messaggio appropriato. – Silvermind

4

Decisamente non uno ArgumentNullException. Se è possibile accedere alla proprietà Children del tuo myDto, ciò significa che myDto, che è l'argomento , è non null. Pertanto, nessun ArgumentNullException come myDto stesso è non null.

Come hai suggerito puoi lanciare un NullReferenceException e aggiungere il tuo messaggio in modo da sapere da dove viene e spiegarlo bene. Questo è completamente logico perché il riferimento alla proprietà che si desidera utilizzare è null.

Come @Silvermind menzionato, la NullReferenceException non deve essere utilizzata. Invece hai altre opzioni come la ArgumentException o la InvalidOperationException. Un'altra opzione potrebbe essere quella di creare il proprio tipo di eccezione che derivi dalla classe Exception.

Esempio:

public class ChildNullException: Exception 
{ 
    public ChildNullException() { } 

    public ChildNullException(string message) 
     : base(message) 
    { 
    } 

    public ChildNullException(string message, Exception inner) 
     : base(message, inner) 
    { 
    } 
} 
+2

Non aumentare [tipi di eccezioni riservate] (http://msdn.microsoft.com/en-us/library/ms182338.aspx) come 'NullReferenceException'. Usa 'InvalidOperationException' con un messaggio appropriato. – Silvermind

+1

@Silvermind grazie per averlo detto, non lo sapevo! :) Ho aggiornato la mia risposta in modo soddisfacente. – Abbas

4

Se l'argomento non è nullo ma in qualche modo non valida, si dovrebbe buttare un ArgumentException:

if(myDto == null) throw new ArgumentNullException("myDto"); 
if(myDto.Child == null) throw new ArgumentException("Property Child must not be null.", "myDto"); 
+0

Penso che questa sia la soluzione migliore. 'ArgumentNullException' si aspetta un parametro che identifica il parametro per nome che era null. 'ArgumentException' è più generico in quanto gli viene fornito un messaggio che dovrebbe identificare il problema (con la proprietà child) e consentire di identificare il parametro root a cui si riferisce. – BrettJ

2

Dalla tua spiegazione vedo che si tratta di un errore di logica del programma, non è problema di dati. È possibile caricare l'entità figlio prima di chiamare questo metodo e tutto funziona correttamente oppure non caricare il figlio e questa logica non può essere eseguita. Quindi, non ha senso lanciare qualche eccezione personalizzata qui, perché dopo aver risolto il problema per la prima volta, il problema non si ripeterà più.Basta vedere lo stack trace di eccezione, correggere la logica del programma e dimenticare questo caso. Utilizzare il gestore di eccezioni globale per quello.

Problemi correlati