关于这个.NET未处理的异常消息:
对象引用未设置为对象的实例.
为什么不呢.网络显示哪个对象是null
?
我知道我可以判断null
并解决错误.然而,为什么不呢.NET帮助指出哪个对象有空引用,哪个表达式触发了NullReferenceException
?
关于这个.NET未处理的异常消息:
对象引用未设置为对象的实例.
为什么不呢.网络显示哪个对象是null
?
我知道我可以判断null
并解决错误.然而,为什么不呢.NET帮助指出哪个对象有空引用,哪个表达式触发了NullReferenceException
?
(有关Visual Studio 2017中新的异常帮助程序的信息,请参阅本答案的结尾)
考虑这个代码:
String s = null;
Console.WriteLine(s.Length);
这将在第二行抛出NullReferenceException
,你想知道为什么.NET并没有告诉您,当抛出异常时,s
是空的.
要理解为什么你得不到这些信息,你应该记住,执行的不是C#source,而是IL:
IL_0001: ldnull IL_0002: stloc.0 // s IL_0003: ldloc.0 // s IL_0004: callvirt System.String.get_Length IL_0009: call System.Console.WriteLine
callvirt
操作码抛出NullReferenceException
,当计算堆栈上的第一个参数是空引用(使用ldloc.0
加载的参数)时,它就会抛出NullReferenceException
.
如果NET应该能够分辨出它是s
,这是一个空引用.它应该以某种方式跟踪计算堆栈上的第一个参数来自s
.在这种情况下,我们很容易看到s
是空的,但如果该值是另一个函数调用的返回值,而不是存储在任何变量中,该怎么办?无论如何,这类信息并不是你想要在虚拟机中记录的.NET虚拟机.
要避免此问题,我建议您在所有公共方法调用中执行参数NULL判断(当然,除非您允许NULL引用):
public void Foo(String s) {
if (s == null)
throw new ArgumentNullException("s");
Console.WriteLine(s.Length);
}
如果将NULL传递给该方法,您将得到一个准确描述问题所在的异常(即s
为NULL).
四年后,Visual Studio2017现在有了一个新的异常帮助器,它将在抛出NullReferenceException
时try 判断什么是NULL.当它是为空的方法的返回值时,它甚至能够为您提供所需的信息:
请注意,这只适用于调试版本.