.net - ¿Por qué una excepción de referencia nula no puede nombrar el objeto que tiene una referencia nula?
exception compiler-construction (5)
Me parece que una gran cantidad de mi tiempo de depuración se emplea para buscar excepciones de referencia nula en sentencias complejas. Por ejemplo:
For Each game As IHomeGame in _GamesToOpen.GetIterator()
¿Por qué, cuando obtengo una NullReferenceException, puedo obtener el número de línea en el seguimiento de la pila, pero no el nombre del objeto que es nulo? En otras palabras, por qué:
Object reference not set to an instance of an object.
en lugar de
_GamesToOpen is not set to an instance of an object.
o
Anonymous object returned by _GamesToOpen.GetIterator() is null.
o
game was set to null.
¿Es estrictamente una elección de diseño, destinada a proteger el anonimato del código o hay una razón de peso en el diseño del compilador para no incluir esta información en la excepción de tiempo de depuración?
En las compilaciones de lanzamiento, los nombres de las variables se eliminan de los símbolos y el código incluso podría optimizarse para no tener una ubicación de memoria específica para una variable, pero solo mantener la referencia en uno de los registros (dependiendo del alcance del uso de la variable) ) Por lo tanto, es posible que no se pueda deducir el nombre de la variable de la ubicación de referencia.
En la construcción de depuración, hay más información disponible sobre las variables. Sin embargo, el objeto de excepción debe funcionar de la misma manera independientemente del sabor de compilación. Por lo tanto, actúa sobre la información mínima a la que puede acceder en cualquier sabor.
Las excepciones son cosas de tiempo de ejecución, las variables son cosas de tiempo de compilación.
De hecho, la variable en tu ejemplo es una expresión . Las expresiones no son siempre variables simples. En el tiempo de ejecución, la expresión se evaluará y se llamará al método sobre el objeto resultante. Si el valor de esa expresión es null
, el tiempo de ejecución arrojará una NullReferenceException
. Asume lo siguiente:
Dim a as New MyObject
Dim b as String = MyObject.GetNullValue().ToString()
¿Qué mensaje de error debería devolver el tiempo de ejecución si el método GetNullValue()
devuelve null
?
Para lenguajes como Java que se compilan en bytecode que se interpretan en una máquina virtual, supongamos que tiene una clase X
con un campo x
, y su valor es null
para una referencia determinada. Si tú escribes
x.foo()
el bytecode podría verse así:
push Xref >> top of stack is ref to instance of X with X.x = null
getField x >> pops Xref, pushes ''null'' on the stack
invokeMethod foo >> pops ''null'' -> runtime exception
El punto es que la operación que necesita una referencia no nula en la pila para operar en ella, como invokeMethod en el ejemplo, no puede y no sabe de dónde proviene esa referencia nula.
Un par de cosas...
1) cuando hagas tus propias excepciones ten esto en cuenta (si estás molesto por esto, alguien más se molestará contigo si lo haces por otra cosa). Dado que la ruta de excepción no debe ser en absoluto la ruta típica, el tiempo dedicado a hacer la excepción tiene información útil que bien vale la pena.
2) como practicante de programación general adopte este estilo y tendrá menos problemas (sí, su código será más largo en términos de líneas, pero ahorrará mucho tiempo):
a) nunca hacer ab (). c (); hacer x = ab (); xc (); (en líneas separadas) de esa manera puedes ver que a era nulo o si el retorno de ab () es nulo.
b) nunca pase el retorno de una llamada a un método como parámetro; siempre pase variables. a (foo ()); debería ser x = foo (); hacha); Este es más para la depuración y poder ver el valor.
No sé por qué entornos como .net y Java no proporcionan una versión del tiempo de ejecución que sí tiene más información sobre este tipo de excepciones, como qué era el índice en una matriz fuera de límites, el nombre de la variable cuando es nulo, etc.
Una forma simple de detectar esto para la depuración para colocar una declaración de Assert antes de usar un objeto, comprobar nulo y mostrar un mensaje significativo.