2010-05-27 15 views
16

"Referencia a objeto no establecida como instancia de un objeto""Referencia de objeto no configurada para una instancia de un objeto": ¿por qué no puede mostrar .NET más detalles?

¿Por qué la excepción no muestran también el nombre del campo de referencia del objeto, o al menos su tipo?

Este es probablemente uno de los errores de tiempo de ejecución más comunes en .NET. Aunque System.Exception tiene un seguimiento de pila, no hay otros detalles útiles.

En el transcurso de un año, paso horas revisando los rastros de pila (a menudo en el código que no escribí), esperando que haya un número de línea de un archivo ".pdb" y luego encuentre la línea en el código y incluso entonces, a menudo no es obvio qué referencia en la línea era nula. Tener el nombre del campo de referencia sería muy conveniente.

Si las instancias System.ArgumentNullException pueden mostrar el nombre del parámetro de método ("valor puede no ser nulo Nombre de parámetro:. valor"), entonces seguramente System.NullReferenceException casos podrían incluir el nombre de la nula campo (o su colección que contiene).

+0

¿Hubo alguna pregunta en alguna parte? – Nix

+0

@Nix: "¿por qué la excepción no muestra también el nombre del campo de referencia del objeto, o al menos su tipo?" –

+1

¡Tuve que votarte, porque esa maldita pregunta me vuelve loco todo el tiempo! :) – Dave

Respuesta

2

Esto ha sido cubierto aquí: Detecting what the target object is when NullReferenceException is thrown

y aquí: Why can't a null-reference exception name the object that has a null reference?

La razón es causa principalmente el tiempo de ejecución no tiene ni idea cuando se encuentra la NRE. Supongo que tendría que devolver el callstack y el árbol de análisis sintáctico, lo que sería realmente costoso.

+0

Gracias por el (primer) enlace. Esa pregunta se relaciona más con el objeto de destino (o la falta de uno) y cómo depurar el problema. Es posible que tenga razón acerca del procesamiento costoso para determinar el origen del NRE, pero especialmente para las compilaciones de depuración, esto sería insignificante en comparación con el esfuerzo de depuración involucrado. –

0

¡No encontré esta excepción tan difícil de tratar!

Si conozco el número de línea. Simplemente inserto un punto de interrupción en esta línea, ejecuto la aplicación en esta línea, y cuando el depurador se detiene, desplazo cada variable/objeto en la línea, y gracias a Visual Studio, me muestra sus valores.

También encontré la ventana Autos muy útil en tales casos, pero el procedimiento que describí anteriormente resuelve mi problema rápidamente.

+0

Gracias, pero sé cómo depurar en VS; Ese no es el punto. Quiero saber por qué .NET no puede ser más explícito con NullReferenceExceptions. A menudo ni siquiera tendría que depurar el código si supiera el nombre del campo no configurado. –

7

La diferencia entre ArgumentNullException y NullReferenceException es que ArgumentNullException siempre se lanza de forma explícita, así:

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

tenía un vistazo rápido en la salida ILDASM, las variables locales son de hecho presente en el interior de IL una función. Sin embargo, todavía no hay API para recuperar esos nombres de forma programática. Según entiendo, sería bastante complejo ya que básicamente necesitaría construir un árbol de análisis sintáctico que represente una función con ámbitos, variables, instrucciones, etc.

Se complica aún más por el hecho de que no son solo variables simples las que pueden arrojar NullReferenceException, pero el resultado de una llamada a una función, una propiedad o una expresión. Podría ser bastante complicado bastante rápido.

Imagínese esto:

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

hay múltiples puntos de fallo allí y la construcción de una cadena que representa lo que realmente está null podría ser complicado.

+0

No es cierto que los nombres de las variables desaparezcan en IL. Ejecute ILDasm o Reflector en un ensamblaje y vea. –

+1

Acabo de hacerlo, tienes razón. –

+1

Gracias por su respuesta actualizada y sus ideas: usted hace una muy buena observación sobre las complejas fuentes de algunas NullReferenceExceptions (mi +1). Todavía parece que para excepciones de referencia de campo nulo simples, incluso sin una API externa, el tiempo de ejecución de .NET podría proporcionar más detalles. En su ejemplo más complejo, todavía no hay suficiente evidencia de por qué el tiempo de ejecución no pudo identificar explícitamente "myObject", "myObject.GetOtherObject() return value", o "myObject.GetOtherObject(). ThirdObject" como la NullReferenceException fuentes. Si se necesita un árbol de análisis sintáctico, ¡que así sea! –

1

Aunque el nombre y el tipo de variable pueden existir en el código MSIL, no existirá en el código nativo cuando el MSIL esté JITted.

Sería increíblemente ineficiente agregar este tipo de comprobación al código nativo durante JITting, esencialmente una sobrecarga cada vez que se quita la referencia de un puntero.

+0

+1 para un punto interesante para un estudio posterior. Sin saber mucho sobre los archivos PDB y cómo se usan en tiempo de ejecución, los números de líneas y columnas donde ocurren las fallas están vinculados de alguna manera con el código JITed, por lo que quizás otra información también lo sea, especialmente para compilaciones Debug. –

Cuestiones relacionadas