35

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?

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.

Jason
  • 1,225
  • 2
  • 16
  • 18
  • 4
    Actually, this is true for a lot of annoying exceptions. Index out of range another culprit. "Index out of range: " would be a huge help. – Jason Apr 16 '10 at 21:52

4 Answers4

22

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:

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.

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.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 1
    The line number would be a great help, but the stack trace doesn't seem to include the line number when the program is run in debug mode away from the development environment. – Jason Apr 16 '10 at 22:08
  • 5
    @Jason: I think you need to copy the PDB file to the program location. The PDB file is what the debugger uses to map from locations in compiled code to locations in source files. – itowlson Apr 16 '10 at 22:22
  • If it is a large object with many setters and one of your setters is the culprit, you could always use ModelState validation and decorate your properties with the [Required] attribute and then do check on ModelState and when it is not valid write out the ModelState and you will have your missing properties. – ewahner Apr 20 '15 at 23:18
  • 1
    @itowlson could you elaborate on that, so if you copy the pdb file to the program location then what happens? – barlop Sep 04 '16 at 21:54
  • @CarlosLanderas couldn't you write an answer then of what solved it. You accepted an answer that said it's not possible, then you said a comment from itowlson solved it but you don't say how. Did it magically work when you copied the pdb file to the program location? – barlop Sep 04 '16 at 21:55
11

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.

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:

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:

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.

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.

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.

Paul Turner
  • 38,949
  • 15
  • 102
  • 166
  • 1
    It seems like a lot of infrastructure to prevent it, since nearly every object is nullable. How do you manage this when you have hundreds of objects in a large program? Some kind of automated code to set those conditions would be perfect. – Jason Apr 17 '10 at 02:42
  • It's about writing guard code where it's appropriate. You need to know that a value is non-null before you de-reference it. If there's a chance it could be null in the logical execution of your code, you have to put some code in to handle those checks. – Paul Turner Apr 17 '10 at 10:33
  • 1
    @Jason, Framework 4.0 has a Code Contracts mechanism that can enforce null-checking (and VS 2010 Premium or above will even statically verify cases that may be null.) There is a fair amount of overhead in setting up the Contracts, but they can be useful for other cases as well. – Dan Bryant Apr 17 '10 at 13:19
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.

Adam Maras
  • 26,269
  • 6
  • 65
  • 91
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

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

Nayan
  • 3,092
  • 25
  • 34