Estamos lanzando un sistema, y a veces recibimos la famosa excepción NullReferenceException
con el mensaje Object reference not set to an instance of an object
.
Sin embargo, en un método en el que tenemos casi 20 objetos, tener un registro que dice que un objeto es nulo, realmente no sirve de nada. Es como decirte, cuando eres el agente de seguridad de un seminario, que un hombre entre 100 asistentes es un terrorista. Eso no te sirve de nada. Debería obtener más información, si desea detectar qué hombre es el hombre amenazante.
Del mismo modo, si queremos eliminar el error, necesitamos saber qué objeto es nulo.
Ahora, algo me ha obsesionado durante varios meses, y eso es:
¿Por qué .NET no nos da el nombre, o al menos el tipo de referencia de objeto, que es nulo? . ¿No puede entender el tipo de reflexión o cualquier otra fuente?
Además, ¿cuáles son las mejores prácticas para comprender qué objeto es nulo? ¿Deberíamos siempre probar manualmente la nulabilidad de los objetos en estos contextos y registrar el resultado? ¿Hay una mejor manera?
Actualización:
la excepción The system cannot find the file specified
tiene la misma naturaleza. No puede encontrar qué archivo, hasta que lo adjunte al proceso y lo depure. Supongo que este tipo de excepciones pueden volverse más inteligentes. ¿No sería mejor si .NET pudiera contarnos en c:\temp.txt doesn't exist.
lugar de ese mensaje general? Como desarrollador, voto sí.
fuente
new
para crear instancias de una clase. ¿Cuándo ayuda realmente tal pista?Respuestas:
El
NullReferenceException
básicamente te dice: lo está haciendo mal. Nada más y nada menos. No es una herramienta de depuración completa, por el contrario. En este caso, diría que lo estás haciendo mal tanto porqueSoy un gran admirador de verificar todo antes de que las cosas empiecen a salir mal y de proporcionar buena información al desarrollador. En resumen: escriba cheques usando
ArgumentNullException
y los me gusta y escriba el nombre usted mismo. Aquí hay una muestra:También puede buscar contratos de código , tiene peculiaridades, pero funciona bastante bien y le ahorra algo de tipeo.
fuente
I only say that checking every object to get sure that it's not null, is not a good method
serio. Es el mejor método. Y no solo nulo, verifique cada argumento para valores razonables. Cuanto antes detecte errores, más fácil será encontrar la causa. No desea tener que retroceder varios niveles en el seguimiento de la pila para encontrar la llamada que causa.Realmente debería mostrar exactamente lo que está tratando de llamar. Es como decir "Hay un problema. Necesitas solucionarlo. Sé lo que es. No te lo voy a decir. Ve a resolverlo". Irónicamente, como la mitad de las respuestas en este Desbordamiento de pila.
Entonces, ¿qué tan útil sería, por ejemplo, si tuviera esto ...
...? Para tener que entrar en el código, recorrerlo y descubrir que lo que está tratando de llamar
null
está bien, pero ¿por qué no solo darnos un poco de ayuda?Estoy de acuerdo en que generalmente es útil recorrer el código para llegar a la respuesta (porque probablemente descubrirá más), pero a menudo se ahorraría mucho tiempo y frustración si el
NullReferenceException
texto fuera más parecido al ejemplo anterior.Sólo digo.
fuente
KeyNotFoundException
y muchas otras molestias ...Su registro debe incluir un seguimiento de la pila, que generalmente le da una pista sobre qué línea del método tiene el problema. Es posible que deba hacer que su versión de lanzamiento incluya símbolos PDB para que tenga una idea de en qué línea se encuentra el error.
Por supuesto, no te ayudará en este caso:
El principio tell don't ask puede ayudar a evitar dicho código.
En cuanto a por qué no se incluye la información, no estoy seguro: sospecho que al menos en una compilación de depuración, si realmente quisieran, podrían resolverlo. Hacer un volcado por caída y abrir en WinDBG puede ayudar.
fuente
Se han creado excepciones como una herramienta para señalar condiciones excepcionales no fatales en la cadena de llamadas. Es decir, no están diseñados como una herramienta de depuración.
Si una excepción de puntero nulo fuera una herramienta de depuración, anularía la ejecución del programa en el acto, permitiendo que se conecte un depurador, apuntándolo directamente a la línea incriminatoria. Esto le daría al programador toda la información de contexto disponible. (Lo cual es más o menos lo que hace un Segfault debido a un acceso de puntero nulo en C, aunque un poco groseramente).
Sin embargo, la excepción de puntero nulo está diseñada como una condición de tiempo de ejecución válida que se puede generar y capturar en el flujo normal del programa. En consecuencia, deben tenerse en cuenta las consideraciones de rendimiento. Y cualquier personalización del mensaje de excepción requiere que se creen, concatenen y destruyan objetos de cadena en tiempo de ejecución. Como tal, un mensaje estático es indiscutiblemente más rápido.
Sin embargo, no estoy diciendo que el tiempo de ejecución no pueda programarse de una manera que produzca el nombre de la referencia incriminatoria. Eso se podría hacer. Simplemente haría excepciones aún más lentas de lo que son. Si alguien se preocupara lo suficiente, tal característica podría incluso hacerse conmutable, de modo que no ralentizaría el código de producción, pero permitiría una depuración más fácil; pero por alguna razón a nadie parece importarle lo suficiente.
fuente
Creo que Cromulent golpeó el clavo en la cabeza, sin embargo, también existe el punto obvio de que si está obteniendo una
NullReferenceException
, tiene variables no inicializadas. El argumento de que tiene alrededor de 20 objetos que se pasan a un método no se puede decir que sea una mitigación: como creador de un fragmento de código, debe ser responsable de sus acciones, lo que incluye su cumplimiento con el resto de una base de código, como así como la correcta y correcta utilización de variables, etc.es oneroso, tedioso y a veces aburrido, pero las recompensas al final valen la pena: muchas veces he tenido que rastrear archivos de registro que pesan varios gigabytes, y casi siempre son útiles. Sin embargo, antes de llegar a esa etapa, el depurador puede ayudarlo, y antes de esa etapa, una buena planificación ahorrará mucho dolor (y tampoco me refiero a un enfoque completamente diseñado para su solución de código: los bocetos simples y algunas notas pueden y lo harán) Ser mejor que nada).
En lo que respecta al
Object reference not set to an instance of an object
código, el código no puede adivinar los valores que nos pueden gustar: ese es nuestro trabajo como programadores, y simplemente significa que ha pasado una variable no inicializada.fuente
Aprende a usar el depurador. Este es exactamente el tipo de cosas para las que está diseñado. Establezca un punto de interrupción en el método en cuestión y listo.
Simplemente revise su código y vea exactamente cuáles son los valores de todas sus variables en ciertos puntos.
Editar: Francamente, estoy sorprendido de que nadie más haya mencionado el uso del depurador todavía.
fuente
Si desea ir con la respuesta de @ stijn y poner cheques nulos en su código, este fragmento de código debería ayudar. Aquí hay información sobre fragmentos de código . Una vez que tenga esto configurado, simplemente escriba
argnull
, presione la pestaña dos veces y luego complete el espacio en blanco.fuente
nameof
por lo que su fragmento podría ser elthrow new ArgumentNullException(nameof($argument$))
que tiene las ventajas de no incluir constantes mágicas, ser revisado por el compilador y trabajar mejor con herramientas de refactorización