2009-12-09 12 views
8

Qualcuno ha delle metriche sull'esecuzione del test nullo rispetto al codice di avvolgimento in un tentativo di cattura?test nullo o prova catch

Sospetto che il test Null sia molto più efficiente, ma non ho dati empirici. .

L'ambiente è C#/3.x rete e il confronto codice è:

Dude x = (Dude)Session["xxxx"]; 
x = x== null ? new Dude(): x; 

contro

Dude x = null; 
try { 
    x = (Dude)Session["xxxx"]; 
    x.something(); 
} catch { 
    x = new Dude(); 
} 

ci sono dei vantaggi ad avvolgere in prova trucco?

risposta

22

Se null è un possibile valore previsto, eseguire il test per null. Se non ti piace il test nullo e hanno un valore di default, è possibile utilizzare l'operatore coelescing nulla per impostare il valore di default:

// value is (Dude)Session["xxxx"] if not null, otherwise it's a new object. 
Dude x = (Dude)Session["xxxx"] ?? new Dude(); 

Salva try/catch per le eccezioni (veramente imprevisti).

+1

null è sempre un valore possibile ... – mson

+0

nel corso regolare degli eventi l'oggetto non deve essere nullo. in questo caso, null si verifica solo se la sessione è scaduta – mson

+2

+1, non utilizzare MAI eccezioni per il flusso di controllo del programma. L'unica volta che vorresti creare un'eccezione è se (Dude) Session ["xxxx"]; essere nulli è stato causa di interrompere il funzionamento del metodo in cui si trovava. Ad esempio, se un valore nullo impedirebbe a tale metodo di eseguire correttamente la funzione che è stato chiamato a eseguire. Come hai scritto la domanda, se tutto ciò che devi fare in questo caso per continuare è creare un nuovo Dude(), allora non è così, quindi un'eccezione non è giustificata. –

1

Le eccezioni richiedono memoria extra e tempo per la cattura. È SEMPRE meglio testare null se è un valore possibile.

1

Un'altra cosa da considerare è che è semplicemente meno codice e più leggibile per fare il test nulla. Solitamente i blocchi try/catch non aggiungono essenzialmente overhead al tuo codice per il caso normale, ma quando l'eccezione viene attivata è piuttosto costoso.

+0

+1. Creare la traccia dello stack è probabilmente ciò che è veramente costoso, qualche ordine di grandezza sopra un test 'null'. – peterchen

0

Sono d'accordo con @Justin Niessner. Inoltre, si consiglia di leggere questo article, che rivela alcuni punti interessanti.

4

penserei che questo sarebbe stato il percorso più veloce:

Dude x = (Dude)Session["xxxx"] ?? new Dude(); 

Il ?? operator è una scorciatoia per il controllo null quando si desidera assegnare un valore specifico, se è nullo.

In ogni caso, le eccezioni finiscono non solo nella creazione di un nuovo oggetto, ma nel generare una traccia dello stack, che rallenta le cose.

+2

non eseguire il cast, utilizzare la parola chiave 'as' (vedere il commento di Mike). lanci di lancio non validi. –

+0

@Stefan: Io uso Java al lavoro, che è probabilmente il motivo per cui non ho pensato alla parola chiave 'as'. – Powerlord

+0

@Stefan: Se 'Session [" xxxx "]' non contiene un 'Dude' o' null', allora vorrei che lo buttasse! Ma suppongo che sia la chiamata dell'OP se vorrebbero un'eccezione in quella situazione o se vorrebbero semplicemente ingoiare silenziosamente la stranezza e restituire un "ragazzo" nuovo di zecca. – LukeH

0

Non si dovrebbe mai usare un try/catch nel normale percorso di codice del programma. Se lo fai, creerai una garbage costante che il garbage collector dovrà elaborare. È molto meglio provare solo per null.

+1

in che modo try/catch crea garbage? Se intendi l'oggetto eccezione, allora è banale. –

+0

Un oggetto di eccezione è banale, ma immagina di creare un oggetto per ogni iterazione del ciclo. –

+0

Dopo aver profilato un'applicazione server che generava migliaia di tali oggetti ogni secondo ed era costantemente in disordine, posso dirti che non è necessariamente banale. Il costo della raccolta dei rifiuti è una delle cose che la maggior parte della gente dimentica quando lavora in Java/C#. – Benj

0

In questo caso, l'eccezione dovrebbe funzionare correttamente, ma ritengo che il numero 1 sia la soluzione migliore. Un'eccezione non dovrebbe essere utilizzata come istruzione If/else, un'eccezione genera un errore, che richiede più risorse di sistema rispetto al primo confronto.

8

Se il codice compatto è ciò che veramente cerca è possibile:

Dude x = Session["xxxx"] as Dude ?? new Dude(); 

l'operatore ?? restituisce il primo valore non nullo di due valori se non v'è alcuna.

Grazie

+0

quando diavolo ha fatto ?? vieni? – mson

+0

@mson è in circolazione da .Net 2.0 – philsquared

+0

grazie a @Phil, non lo sapevo nemmeno io! –

0

MAI utilizzare le eccezioni per il flusso di controllo del programma. L'unica volta in cui si vorrebbe creare un'eccezione è che se (Dude)Session["xxxx"]; è nullo si è verificato un arresto del funzionamento del metodo in cui ci si trovava., se un valore nullo impedirebbe a tale metodo di eseguire correttamente la funzione che è stato chiamato a eseguire. Come hai scritto la domanda, se tutto ciò che devi fare in questo caso per continuare è creare un nuovo Dude(), allora non è così, quindi un'eccezione non è giustificata.

0

Utilizzare eccezioni per casi eccezionali, non per il normale flusso del programma.

Se si devono eseguire molti controlli Null, prendere in considerazione l'utilizzo dello Null Object Pattern invece di utilizzare valori null reali per indicare un valore inesistente che forse ha un comportamento predefinito.

Ero sempre un po 'sospettoso di Null Object Pattern fino a quando non ho iniziato a utilizzare Objective-C in cui è il comportamento predefinito. Pulisce davvero molto codice (ma non è sempre sempre appropriato, ovviamente).

0

Come si desidera verificare null, è ciò che si dovrebbe fare. È più efficiente di prendere un'eccezione.

Inoltre, rilevando le eccezioni dovresti essere molto specifico e catturare esattamente esattamente ciò che ti aspetti. Se rilevi un qualsiasi tipo di eccezione, rischi di rilevare errori che non avevi previsto e gestirli nel modo sbagliato.