2011-01-07 12 views
7

Che typeo d'eccezione lanceresti da una proprietà di sola lettura quando l'oggetto che viene utilizzato per il valore di ritorno è nulloChe tipo di eccezione per gettare

public class TestClass 
{ 
    SomeObject obj; 
    public string NameOfObject 
    { 
     get 
     { 
      if(obj == null) 
      { // what exception type to throw here } 
      return obj.Name; 
     } 
} 
+2

Forse questa è una domanda per il suo argomento, ma perché buttarne uno a tutti? – 4imble

+0

IMPORTANTE Nota: una proprietà dovrebbe (quasi) non generare mai un'eccezione durante la lettura. (InvalidOperation è uno che puoi comunque). http://msdn.microsoft.com/en-us/library/bb386039.aspx – FastAl

risposta

7

Un InvalidOperationException è quello che vorrei utilizzare in questo caso, perché l'accesso alla proprietà non è valido per lo stato corrente dell'oggetto.

Secondo la documentazione MSDN:
"L'eccezione che viene generata quando una chiamata al metodo non è valida per lo stato corrente dell'oggetto."
anche:
"InvalidOperationException viene utilizzato nei casi in cui l'errore di richiamare un metodo è causato da motivi diversi da argomenti non validi."

In questo caso obj non è un argomento, che è il motivo per cui avrei magra verso "InvalidOperationException"

Il motivo per cui non vorrei gettare un NullReferenceException qui: se non ha ancora aggiungere qualsiasi codice speciale, questo è il eccezione che ".Net" avrebbe gettato, quindi perché aggiungere codice ridondante?

2

A meno che non si sta dicendo da qualche parte che questa proprietà non sarà mai essere nullo, perché dovresti lanciare un'eccezione?

Detto questo, se hai garantito che, vorrei buttare un InvalidOperationException.

InvalidOperationException è

L'eccezione generata quando una chiamata metodo è valido per lo stato corrente dell'oggetto .

9

Vorrei buttare un InvalidOperationException.

ArgumentNullException lancio solo se i parametri dei metodi sono nulli.

Se il parametro metodi è in uno stato non valido, viene generato un valore ArgumentException.

+3

Se si esegue 'new InvalidOperationException()' senza passare il proprio messaggio, il messaggio predefinito è "Operazione non valida a causa dello stato corrente di l'oggetto. ", che è esattamente giusto. –

+0

+1 per le informazioni di dettaglio;) – Khh

4

Non si dovrebbe lanciare NullReferenceException. È riservato alle situazioni in cui un oggetto nullo è dereferenziato. In questo caso, se dovessi lanciare NullReference, potresti anche lasciare il check null e lasciare che sia il framework a lanciarlo quando tenti di accedere al Nome dell'obj.

Vorrei buttare invece InvalidOperationException.

+0

+1 per la spiegazione del perché non utilizzare una NullReferenceException – Khh

1

mi piacerebbe gettare un InvalidOperationException, ma solo se: - E 'legale per obj di essere null, ed è responsabilità dell'utente per verificare la presenza di questo, o - non è legale per obj di essere null in primo luogo (cioè, obj != null è una classe invariante)

Se nessuno di quanto sopra è il caso (cioè, è legale per obj di essere null, e codice utente non è espressamente richiesta per verificare questa prima dell'uso la proprietà), quindi non mi butto affatto ma piuttosto restituisco null.

1

Vorrei rivisitare il progetto in modo che questo stato non possa esistere in primo luogo, cioè obj è nullo. Generalmente da una prospettiva API dovresti essere in grado di chiamare un getter in buona fede che non esploderà a causa del fatto che l'oggetto si trova in uno stato sconosciuto.

Ad esempio, perché non utilizzare 'SomeObject obj' come parametro del costruttore e utilizzare la convalida dell'argomento nel punto di costruzione. Ciò assicurerà che lo stato di 'obj' sia sempre corretto, cioè non nulla dopo la costruzione.

Esistono molti modelli che possono essere utilizzati per garantire che un oggetto abbia uno stato corretto quando diventa disponibile per l'utente.

2

Ognuno ha coperto l'ovvio, quindi ecco un'altra opzione.

Se la classe deve essere inizializzata in qualche modo (il proprio SomeObject deve essere impostato ad un certo punto), considerare l'implementazione di ISupportInitialize. Ciò indica agli utenti della tua classe che non è in uno stato valido prima della chiamata allo EndInit(). Sfortunatamente, non esiste un generale preesistente NotInitializedException che è possibile utilizzare (ce ne sono alcuni ma sono specifici per determinati spazi dei nomi), quindi suggerirei di associare l'implementazione dell'interfaccia con la creazione di tale eccezione.

Gli utenti devono prima chiamare il numero BeginInit(), quindi configurare l'istanza, quindi chiamare EndInit(). Nella chiamata allo EndInit(), verificare lo stato dell'istanza. Se non è correttamente inizializzato, puoi lanciare un InvalidOperationException. Se gli utenti tentano di utilizzare la tua istanza prima di essere inizializzata, invierai la tua NotInitializedException.

È un po 'più di lavoro, ma il vantaggio è che si sta creando un "pozzo di successo" più ampio per i propri utenti, assicurando che utilizzino correttamente le classi non riuscendo in modo rapido e precoce e dalla definizione stessa del proprio tipo (l'interfaccia è abbastanza chiara su quello che ti aspetti). Ti dà anche più "spazio", per così dire, per documentare come la tua classe dovrebbe essere usata.

+0

Ho familiarità con ISupportInitialize e il suo utilizzo in contesti DI (ad esempio l'iniezione di proprietà). Non sono così sicuro che questo jive sia così efficace come una API programmatic \ user. Questo modello è molto usato in WinForms e WPF, ma sospetto che poche persone ne siano a conoscenza, quindi non sono così sicuro dell'angolo del "pozzo del successo". Questo modello viene utilizzato nei framework dell'interfaccia utente a causa della necessità di un costruttore predefinito. In una API utente ciò non deve necessariamente essere il caso, altri meccanismi possono essere utilizzati per garantire che un oggetto venga creato con lo stato corretto ad es. parametri costruttore e validazione arg. –

+1

@chi tutto vero. Immaginavo che anche dopo quindici risposte "InvalidOperationException" ci fosse spazio per almeno un sostituto. La buca è più grande, imho, perché costringe gli utenti a "configurare" l'istanza, il che significa che gli utenti devono considerare cosa significa realmente.È un po 'più chiaro di questo o quel metodo/proprietà che lancia un'eccezione se non hai ancora fatto qualcosa. – Will

+0

Concordato - Penso che ci siano modi migliori per risolvere il problema che lanciare un "InvalidOperationException". Ero anche sull'angolo della soluzione alternativa. –

1

Guardando il codice fornito e non sapendo nulla delle ipotesi di progettazione, direi che non si dovrebbe testare obj == null e lasciare che il framework lanci un NullReferenceException. Allora perché vuoi questo test? Una ragione per cui potrei pensare è che vuoi avere un messaggio di errore più significativo per il debug, ma dovresti usare Debug.Assert(obj != null, "Your message here").

Problemi correlati