对象引用没有设置为对象的实例——如何在异常中找到违规对象的名称?

时间:2022-01-16 18:56:46

This is the bane of my programming existence. After deploying an application, when this error crops up, no amount of debug dump tells you WHAT object was not instantiated. I have the call stack, that's great, it tells me roughly where the object is, but is there any way to get .NET to tell me the actual name of the object?

这是我编程生涯的祸根。在部署应用程序之后,当出现这个错误时,没有多少调试转储会告诉您什么对象没有实例化。我有调用堆栈,很好,它粗略地告诉我对象在哪里,但是有没有办法让。net告诉我对象的实际名称?

If you catch them while debugging, of course the program breaks right on the offending creature, but if it happens after the program is in the wild, good luck.

如果你在调试过程中捕捉到它们,当然程序就会破坏这个讨厌的生物,但是如果程序在野外发生,那就祝你好运了。

There has to be a way.

总有办法的。

I've explored the exceptions returned in these instances and there is just nothing helpful.

我已经研究了这些实例中返回的异常,没有任何有用的东西。

4 个解决方案

#1


18  

No, it's not possible. The exception happens because a reference is null, and references doesn't have names. Variables and class/struct members have names, but it's not certain that the reference is stored in either of those. The reference could for example be created like this:

不,这是不可能的。发生异常是因为引用为null,引用没有名称。变量和类/结构体成员都有名称,但不能确定引用是否存储在这两个名称中。例如,可以这样创建引用:

someObject.GetInstance().DoSomething();

If the GetInstance method returns null, there is a null reference exception when you try to use the reference to call DoSomething. The reference is just a return value from the method, it's not stored in a variable, so there is nothing to get a name from.

如果GetInstance方法返回null,那么当您试图使用引用调用DoSomething时,会有一个null引用异常。引用只是方法的返回值,它不是存储在一个变量中,所以没有任何东西可以得到一个名称。

If you have debugging information in the compiled assembly, you will get the line number in the stack trace in the exception, but that is as close as you can get.

如果在编译后的程序集中有调试信息,您将在异常中获得堆栈跟踪中的行号,但这是您所能得到的最接近的行号。

#2


8  

NullReferenceException is the most evil of all exceptions in an application. It means a possibly-null reference wasn't checked for a null value before it was accessed.

NullReferenceException是应用程序中最坏的异常。这意味着可能的空引用在被访问之前没有检查空值。

It's evil, because the runtime can't determine what you were expecting to find in the reference, so it can't tell you what precisely failed to be de-referenced.

这很糟糕,因为运行时不能确定您期望在引用中找到什么,所以它不能告诉您什么是要取消引用的。

The stack trace is your only friend in this exception, where it can at least identify which method threw the exception. If your code is neat enough, it should identify a small amount of code to check through.

堆栈跟踪是这个异常中惟一的朋友,它至少可以识别抛出异常的方法。如果您的代码足够整洁,它应该标识少量代码以供检查。

Additionally, if you're running with a debug build and have the debugging information with the assemblies, you'll even get source line numbers in the stack trace, so you can know exactly what line the method failed on.

此外,如果您正在运行一个调试版本,并拥有与程序集的调试信息,那么您甚至可以在堆栈跟踪中获得源行号,这样您就可以知道该方法失败的确切位置。


The real answer is to prevent this exception from ever being thrown. It's an indicator that some code was poorly written, failing to deal with the scenario where a reference was null.

真正的答案是防止这个异常被抛出。这表明一些代码编写得很糟糕,无法处理引用为空的情况。

If you have a method being called where you need to do something with a reference-type argument that needs to be de-referenced at some point, check for null and throw ArgumentNullException, indicating the name of the parameter:

如果有一个方法被调用,需要对引用类型的参数进行某些操作,需要在某个时候取消引用,那么检查null并抛出ArgumentNullException,指示参数的名称:

if(parameter == null)
    throw new ArgumentNullException("parameter");

If you are performing an operation within a class and a settable property can be set to null, check before de-referencing it and throw an InvalidOperationException indicating the problem:

如果您正在一个类中执行一个操作,并且可以将可设置属性设置为null,那么请在取消引用前进行检查,并抛出一个InvalidOperationException,指出问题所在:

if(Property == null)
    throw new InvalidOperationException("Property cannot be null.");

You should also make sure that all methods you're calling that can return reference types are guaranteed to return a value. For all those that are not, make similar checks for null and handle the case appropriately.

您还应该确保所调用的所有能够返回引用类型的方法都保证返回一个值。对于所有未检查的,对null进行类似的检查,并适当地处理这种情况。

EDIT:

编辑:

To clarify, I'm not suggesting you perform a check on every reference-type variable before you de-reference it. That would be madness.

为了澄清,我并不是建议您在取消引用之前对每个引用类型变量执行检查。这将是疯狂的。

It's about understanding where a variable can be assigned null and where it cannot. If you assign a private field in a class to a non-null value in the constructor, and the value is never assigned again, you don't need to check whether the value is null; the design of your class has made sure it never can be.

它是关于理解一个变量在哪里可以赋值为null,在哪里不能赋值。如果您将类中的一个私有字段分配给构造函数中的一个非空值,并且该值再也不会被分配,那么您不需要检查该值是否为null;你的课程设计确保了它永远不会是。

A well-designed object will restrict the opportunities for null values being assigned and will use guard code where appropriate to throw exceptions when a null value can be present.

设计良好的对象将限制分配空值的机会,并将在适当的地方使用保护代码,以便在出现空值时抛出异常。

#3


0  

This is one of those instances where you really need to attach to the application and step through the general area of the offending code to figure out where that null reference is coming from.

在这些实例中,您确实需要附加到应用程序,并通过违规代码的一般区域来确定null引用来自何处。

#4


0  

I think currently the best you can get is the line no.

我认为目前你能得到的最好的东西是线号。

StackTrace: at test_003.Form1.button1_Click(Object sender, EventArgs e) in C:\Documents and Settings\...\Projects\test_003\test_003\Form1.cs:line 52

加:test_003.Form1。button1_Click C:\Documents and Settings\...\Projects\test_003\test_003\Form1.(对象发送方,EventArgs e)cs:线52

If they do something in future about this problem, it would be great.

如果他们将来能对这个问题做点什么,那就太好了。

#1


18  

No, it's not possible. The exception happens because a reference is null, and references doesn't have names. Variables and class/struct members have names, but it's not certain that the reference is stored in either of those. The reference could for example be created like this:

不,这是不可能的。发生异常是因为引用为null,引用没有名称。变量和类/结构体成员都有名称,但不能确定引用是否存储在这两个名称中。例如,可以这样创建引用:

someObject.GetInstance().DoSomething();

If the GetInstance method returns null, there is a null reference exception when you try to use the reference to call DoSomething. The reference is just a return value from the method, it's not stored in a variable, so there is nothing to get a name from.

如果GetInstance方法返回null,那么当您试图使用引用调用DoSomething时,会有一个null引用异常。引用只是方法的返回值,它不是存储在一个变量中,所以没有任何东西可以得到一个名称。

If you have debugging information in the compiled assembly, you will get the line number in the stack trace in the exception, but that is as close as you can get.

如果在编译后的程序集中有调试信息,您将在异常中获得堆栈跟踪中的行号,但这是您所能得到的最接近的行号。

#2


8  

NullReferenceException is the most evil of all exceptions in an application. It means a possibly-null reference wasn't checked for a null value before it was accessed.

NullReferenceException是应用程序中最坏的异常。这意味着可能的空引用在被访问之前没有检查空值。

It's evil, because the runtime can't determine what you were expecting to find in the reference, so it can't tell you what precisely failed to be de-referenced.

这很糟糕,因为运行时不能确定您期望在引用中找到什么,所以它不能告诉您什么是要取消引用的。

The stack trace is your only friend in this exception, where it can at least identify which method threw the exception. If your code is neat enough, it should identify a small amount of code to check through.

堆栈跟踪是这个异常中惟一的朋友,它至少可以识别抛出异常的方法。如果您的代码足够整洁,它应该标识少量代码以供检查。

Additionally, if you're running with a debug build and have the debugging information with the assemblies, you'll even get source line numbers in the stack trace, so you can know exactly what line the method failed on.

此外,如果您正在运行一个调试版本,并拥有与程序集的调试信息,那么您甚至可以在堆栈跟踪中获得源行号,这样您就可以知道该方法失败的确切位置。


The real answer is to prevent this exception from ever being thrown. It's an indicator that some code was poorly written, failing to deal with the scenario where a reference was null.

真正的答案是防止这个异常被抛出。这表明一些代码编写得很糟糕,无法处理引用为空的情况。

If you have a method being called where you need to do something with a reference-type argument that needs to be de-referenced at some point, check for null and throw ArgumentNullException, indicating the name of the parameter:

如果有一个方法被调用,需要对引用类型的参数进行某些操作,需要在某个时候取消引用,那么检查null并抛出ArgumentNullException,指示参数的名称:

if(parameter == null)
    throw new ArgumentNullException("parameter");

If you are performing an operation within a class and a settable property can be set to null, check before de-referencing it and throw an InvalidOperationException indicating the problem:

如果您正在一个类中执行一个操作,并且可以将可设置属性设置为null,那么请在取消引用前进行检查,并抛出一个InvalidOperationException,指出问题所在:

if(Property == null)
    throw new InvalidOperationException("Property cannot be null.");

You should also make sure that all methods you're calling that can return reference types are guaranteed to return a value. For all those that are not, make similar checks for null and handle the case appropriately.

您还应该确保所调用的所有能够返回引用类型的方法都保证返回一个值。对于所有未检查的,对null进行类似的检查,并适当地处理这种情况。

EDIT:

编辑:

To clarify, I'm not suggesting you perform a check on every reference-type variable before you de-reference it. That would be madness.

为了澄清,我并不是建议您在取消引用之前对每个引用类型变量执行检查。这将是疯狂的。

It's about understanding where a variable can be assigned null and where it cannot. If you assign a private field in a class to a non-null value in the constructor, and the value is never assigned again, you don't need to check whether the value is null; the design of your class has made sure it never can be.

它是关于理解一个变量在哪里可以赋值为null,在哪里不能赋值。如果您将类中的一个私有字段分配给构造函数中的一个非空值,并且该值再也不会被分配,那么您不需要检查该值是否为null;你的课程设计确保了它永远不会是。

A well-designed object will restrict the opportunities for null values being assigned and will use guard code where appropriate to throw exceptions when a null value can be present.

设计良好的对象将限制分配空值的机会,并将在适当的地方使用保护代码,以便在出现空值时抛出异常。

#3


0  

This is one of those instances where you really need to attach to the application and step through the general area of the offending code to figure out where that null reference is coming from.

在这些实例中,您确实需要附加到应用程序,并通过违规代码的一般区域来确定null引用来自何处。

#4


0  

I think currently the best you can get is the line no.

我认为目前你能得到的最好的东西是线号。

StackTrace: at test_003.Form1.button1_Click(Object sender, EventArgs e) in C:\Documents and Settings\...\Projects\test_003\test_003\Form1.cs:line 52

加:test_003.Form1。button1_Click C:\Documents and Settings\...\Projects\test_003\test_003\Form1.(对象发送方,EventArgs e)cs:线52

If they do something in future about this problem, it would be great.

如果他们将来能对这个问题做点什么,那就太好了。