关于此.NET未处理的异常消息:
你调用的对象是空的。
.NET为什么不显示哪个对象null?
我知道我可以检查null并解决错误。但是,.NET为什么不帮助指出哪个对象具有空引用,哪个表达式触发了NullReferenceException?
关于此.NET未处理的异常消息:
你调用的对象是空的。
.NET为什么不显示哪个对象null?
我知道我可以检查null并解决错误。但是,.NET为什么不帮助指出哪个对象具有空引用,哪个表达式触发了NullReferenceException?
Answers:
(有关Visual Studio 2017中新的异常帮助器的信息,请参见此答案的结尾)
考虑以下代码:
String s = null;
Console.WriteLine(s.Length);
这将NullReferenceException在第二行中引发a ,您想知道为什么s在引发异常时.NET不会告诉您那是null。
要了解为什么没有得到那条信息,您应该记住执行的不是C#源,而是IL:
IL_0001:ldnull IL_0002:stloc.0 // s IL_0003:ldloc.0 // s IL_0004:callvirt System.String.get_Length IL_0009:调用System.Console.WriteLine
当评估堆栈上的第一个参数为空引用(使用加载的参数)时,它是callvirt引发的操作码。NullReferenceExceptionldloc.0
如果.NET应该能够说出那s是一个空引用,则它应该以某种方式跟踪评估堆栈上的第一个参数源自表单s。在这种情况下,我们很容易看到它为snull,但是如果该值是另一个函数调用的返回值并且未存储在任何变量中怎么办?无论如何,这种信息不是您想要在虚拟机(如.NET虚拟机)中跟踪的信息。
为避免此问题,我建议您在所有公共方法调用中执行参数空值检查(除非您当然允许空值引用):
public void Foo(String s) {
if (s == null)
throw new ArgumentNullException("s");
Console.WriteLine(s.Length);
}
如果将null传递给该方法,则将获得一个准确描述问题所在的异常(即snull)。
四年后,Visual Studio 2017现在拥有一个新的异常帮助器,它将尝试在NullReferenceException抛出a时判断是否为null 。当方法的返回值为null时,它甚至可以为您提供所需的信息:
请注意,这仅在DEBUG构建中有效。
null。
null请注意,OP并不声称他或她想知道对于发布版本以及调试版本可能就足够了。
null)与返回该对象引用的源文件行和列相关联的问题。
在以下情况下,您希望如何显示错误消息?
AnyObject.GetANullObject().ToString();
private object GetANullObject()
{
return null;
}
没有变量名称可在此处报告!
Object reference obtained from AnyObject.GetANullObject() not set to an instance of an object.错误消息的信息。
好吧,这取决于微软的工程师。但是您显然可以使用调试器并添加监视功能,以找出其中哪些有问题。
但是,例外情况是NullReferenceException该引用不存在。您根本无法获得尚未创建的对象。
but why .NET don't tell us which object is null?
因为它不知道哪个对象为空。该对象根本不存在!
我说的是将C#编译为.NET IL代码,情况也是如此。.NET IL代码不知道名称或表达式。它只知道引用及其位置。在这里,您也无法获得不存在的内容。表达式或变量名不存在。
哲学:如果您一开始没有鸡蛋,就不能制作蛋卷。