Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# &引用;对象引用未设置为对象的实例";:为什么可以';t.NET显示更多细节?_C#_.net_Vb.net - Fatal编程技术网

C# &引用;对象引用未设置为对象的实例";:为什么可以';t.NET显示更多细节?

C# &引用;对象引用未设置为对象的实例";:为什么可以';t.NET显示更多细节?,c#,.net,vb.net,C#,.net,Vb.net,“对象引用未设置为对象的实例” 为什么异常不同时显示对象引用字段的名称,或者至少显示其类型 这可能是.NET中最常见的运行时错误之一。尽管System.Exception有堆栈跟踪,但没有其他有用的详细信息 在一年的时间里,我花了数小时筛选堆栈跟踪(通常是在我没有编写的代码中),希望有一个“.pdb”文件中的行号,然后在代码中找到该行,即使这样,行上的哪个引用是空的也往往不明显。拥有引用字段的名称将非常方便 如果System.ArgumentNullException实例可以显示方法参数的名称(

“对象引用未设置为对象的实例”

为什么异常不同时显示对象引用字段的名称,或者至少显示其类型

这可能是.NET中最常见的运行时错误之一。尽管System.Exception有堆栈跟踪,但没有其他有用的详细信息

在一年的时间里,我花了数小时筛选堆栈跟踪(通常是在我没有编写的代码中),希望有一个“.pdb”文件中的行号,然后在代码中找到该行,即使这样,行上的哪个引用是空的也往往不明显。拥有引用字段的名称将非常方便


如果System.ArgumentNullException实例可以显示方法参数的名称(“值不能为null。参数名称:”),那么System.NullReferenceException实例肯定可以包括null字段(或其包含集合)的名称。

这里已经介绍了这一点:

在这里:


原因主要是运行时不知道何时会遇到NRE。我猜它必须返回调用堆栈并通过解析树,这将非常昂贵

我没有发现这个异常很难处理

如果我知道电话号码。我只是在这一行插入一个断点,将应用程序运行到这一行,当调试器停止时,我将鼠标悬停在这一行中的每个变量/对象上,多亏了VisualStudio,它向我显示了它们的值


我还发现自动窗口在这种情况下非常有用,但我上面描述的过程很快解决了我的问题。

NullReferenceException
之间的区别在于
ArgumentNullException
总是这样显式抛出:

if (parameter == null)
  throw new ArgumentNullException("parameter");
快速查看ILDASM输出,局部变量确实存在于函数的IL中。然而,仍然没有API以编程方式检索这些名称。我的理解是,这将是相当复杂的,因为您基本上需要构建一个用作用域、变量、语句等表示函数的解析树

更复杂的是,不仅仅是简单的变量可以抛出
NullReferenceException
,而是函数调用、属性或表达式的结果。我很快就会变得很复杂

想象一下:

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

这里存在多个故障点,构建一个表示实际为
null的字符串可能很棘手。

即使变量名和类型可能存在于MSIL代码中,但当MSIL被JIT时,它不会存在于本机代码中


在JITting过程中向本机代码添加这种检查是非常低效的,这基本上是一种在指针被取消引用时的开销。

这里有什么问题吗?@Nix:“为什么异常不同时显示对象引用字段的名称,或者至少是它的类型?”我不得不向您投票,因为那个该死的问题一直让我发疯!:)因为变量的名称在编译时就丢失了。@Nix:这不是真的。即使没有PDB文件的发布版本也可以使用Reflector进行反汇编,以显示变量和成员名称。感谢(第一)链接。这个问题更多地涉及目标对象(或缺少目标对象),以及如何调试问题。在确定NRE的源代码时,您可能对昂贵的处理是正确的,但特别是对于调试构建,与所涉及的调试工作相比,这将是微不足道的;这不是重点。我想知道为什么.NET不能更明确地包含NullReferenceExceptions。通常,如果我知道unset字段的名称,我甚至不需要调试代码。在程序集上运行ILDasm或Reflector并查看。感谢您更新的答案及其见解-您对某些NullReferenceException(my+1)的复杂源有了很好的理解。不过,对于简单的空字段引用异常,.NET运行时似乎可以提供更多细节,即使没有外部API。在更复杂的示例中,仍然没有足够的证据确切说明运行时无法将“myObject”、“myObject.GetOtherObject()返回值”或“myObject.GetOtherObject().ThirdObject”明确标识为NullReferenceException源的原因。如果它需要一个解析树,那么就这样吧+1为进一步研究提供了一个有趣的观点。在不太了解PDB文件及其在运行时的使用方式的情况下,发生故障的行号和列号以某种方式与JIT代码相关联,因此可能还有其他信息,特别是对于调试构建。