2010-05-27 21 views
16

"riferimento oggetto non impostato a un'istanza di un oggetto""Riferimento oggetto non impostato su un'istanza di un oggetto": perché .NET non può mostrare ulteriori dettagli?

Perché l'eccezione non mostra anche il nome del campo riferimento all'oggetto, o almeno il suo tipo?

Questo è probabilmente uno degli errori di runtime più comuni in .NET. Sebbene System.Exception abbia una traccia dello stack, non ci sono altri dettagli utili.

Nel corso di un anno trascorro ore a passare in rassegna le tracce dello stack (spesso in codice che non ho scritto), sperando che ci sia un numero di riga da un file ".pdb", quindi trovando la riga nel codice, e anche allora spesso non è ovvio quale riferimento sulla linea fosse nullo. Avere il nome del campo di riferimento sarebbe molto conveniente.

Se le istanze System.ArgumentNullException può mostrare il nome del parametro del metodo ("valore non può essere nullo Nome di parametro:. valore"), allora sicuramente System.NullReferenceException casi potrebbero includere il nome del nulla campo (o la sua raccolta di contenuti).

+0

C'era una domanda da qualche parte? – Nix

+0

@Nix: "perché l'eccezione non mostra anche il nome del campo di riferimento dell'oggetto, o almeno il suo tipo?" –

+1

Ho dovuto revocarti, perché quella stessa dannata domanda mi fa impazzire tutto il tempo! :) – Dave

risposta

2

Questo è stato coperto qui: Detecting what the target object is when NullReferenceException is thrown

e qui: Why can't a null-reference exception name the object that has a null reference?

Il motivo è principalmente causare il runtime non ha idea di quando si incontra il NRE. Suppongo che avrebbe dovuto ripristinare il callstack e l'albero di analisi, il che sarebbe molto costoso.

+0

Grazie per il (primo) link. Questa domanda riguarda più l'oggetto target (o la mancanza di uno) e come eseguire il debug del problema. Potrebbe essere corretto il costoso processo di determinazione della fonte di NRE, ma soprattutto per i build di Debug, questo sarebbe insignificante rispetto allo sforzo di debug in questione. –

0

Non ho trovato questa eccezione così difficile da gestire!

Se conosco il numero di riga. Inserisco semplicemente un punto di interruzione su questa linea, eseguo l'applicazione su questa linea e quando il debugger si arresta, posiziono il mouse su ogni variabile/oggetto nella riga e, grazie a Visual Studio, mi mostra i loro valori.

Inoltre ho trovato la finestra di Auto molto utile in questi casi, ma la procedura descritta sopra risolve rapidamente il mio problema.

+0

Grazie, ma so come eseguire il debug in VS; non è questo il punto. Voglio sapere perché .NET non può essere più esplicito con NullReferenceExceptions. Spesso non avrei nemmeno bisogno di eseguire il debug del codice se conoscessi il nome del campo unset. –

7

La differenza tra ArgumentNullException e NullReferenceException è che ArgumentNullException è sempre gettato in modo esplicito in questo modo:

if (parameter == null) 
    throw new ArgumentNullException("parameter"); 

aveva uno sguardo rapido in uscita ILDASM, le variabili locali sono infatti presenti all'interno IL di una funzione. Non c'è ancora, tuttavia, nessuna API per recuperare questi nomi in modo programmatico. La mia comprensione è che sarebbe abbastanza complesso in quanto avresti fondamentalmente bisogno di costruire un albero di analisi che rappresenti una funzione con ambiti, variabili, istruzioni ecc.

E 'ulteriormente complicato dal fatto che non sono solo semplici variabili che possono generare NullReferenceException, ma il risultato di una chiamata di funzione, una proprietà o un'espressione. Potrei diventare abbastanza complicato abbastanza velocemente.

Immaginate questo:

internalObject.OtherProperty = myObject.GetOtherObject().ThirdObject.SomeProperty == "value" 
? myObject.OtherProperty 
: myObject.GetSomethingElse(); 

ci sono più punti di guasto là e costruire una stringa che rappresenta ciò che è effettivamente null potrebbe essere difficile.

+0

Non è vero che i nomi delle variabili scompaiono in IL. Eseguire ILDasm o Reflector su un assieme e vedere. –

+1

L'ho appena fatto, hai ragione. –

+1

Grazie per la tua risposta aggiornata e le sue intuizioni: fai un ottimo punto sulle complesse fonti di alcune NullReferenceExceptions (il mio +1). Tuttavia sembra che per semplici eccezioni di riferimento del campo nullo, anche senza un'API esterna, il runtime .NET possa fornire maggiori dettagli. Nell'esempio più complesso, non vi sono ancora prove sufficienti per spiegare perché il runtime non sia in grado di identificare esplicitamente "myObject", "myObject.GetOtherObject() return value" o "myObject.GetOtherObject(). ThirdObject" come NullReferenceException fonti. Se serve un albero di analisi, allora così sia! –

1

Anche se il nome e il tipo di variabile possono esistere nel codice MSIL, esso non esisterà nel codice nativo quando MSIL è JITted.

Sarebbe incredibilmente inefficiente aggiungere questo tipo di controllo al codice nativo durante JITting - essenzialmente un sovraccarico ogni volta che un puntatore viene dereferenziato.

+0

+1 per un punto interessante per ulteriori studi. Senza sapere molto sui file PDB e sul modo in cui vengono utilizzati in fase di runtime, i numeri di riga e colonna in cui si verificano i guasti sono collegati in qualche modo al codice JIT, quindi forse potrebbero esserci anche altre informazioni, soprattutto per le build di Debug. –

Problemi correlati