Object reference not set to an instance of an object.Why doesn't .NET show which object is `null`?

C#.Net

C# Problem Overview


Regarding this .NET unhandled exception message:

> Object reference not set to an instance of an object.

Why doesn't .NET show which object is null?

I know that I can check for null and resolve the error. However, why doesn't .NET help pointing out which object has a null-reference and which expression triggered the NullReferenceException?

C# Solutions


Solution 1 - C#

(For information about the new exception helper in Visual Studio 2017 see the end of this answer)


Consider this code:

String s = null;
Console.WriteLine(s.Length);

This will throw a NullReferenceException in the second line and you want to know why .NET doesn't tell you that it was s that was null when the exception was thrown.

To understand why you don't get that piece of information you should remember that it is not C# source that executes but rather 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

It is the callvirt opcode that throws the NullReferenceException and it does that when the first argument on the evaluation stack is a null reference (the one that was loaded using ldloc.0).

If .NET should be able to tell that it was s that was a null reference it should in some way track that the first argument on the evaluation stack originated form s. In this case it is easy for us to see that it is s that was null but what if the value was a return value from another function call and not stored in any variable? Anyway, this kind of information is not what you want to keep track of in a virtual machine like the .NET virtual machine.


To avoid this problem I suggest that you perform argument null checking in all public method calls (unless of course you allow the null reference):

public void Foo(String s) {
  if (s == null)
    throw new ArgumentNullException("s");
  Console.WriteLine(s.Length);
}

If null is passed to the method you get an exception that precisely describes what the problem is (that s is null).


Four years later Visual Studio 2017 now has a new exception helper that will try to tell what is null when a NullReferenceException is thrown. It is even able to give you the required information when it is the return value of a method that is null:

Visual Studio 2017 exception helper

Note that this only works in a DEBUG build.

Solution 2 - C#

How do you want the error message in the following case look like?

AnyObject.GetANullObject().ToString();

private object GetANullObject()
{
  return null;
}

No variable names to report here!

Solution 3 - C#

Well, that's upto engineers at Microsoft to answer. But you can obviously use a debugger and add watch to find out which of those has a problem.

However, the exception is NullReferenceException which means the reference does not exist . You can't get the object which hasn't been created at all.

but why .NET don't tell us which object is null? Because it does not know which object is null. The object simply does not exist!

Same is the case when I say, C# is compiled to .NET IL code. The .NET IL code does not know the names or expressions. It only knows references and their location. Here too, you cannot get what does not exist. The expression or the variable name does not exist.

Philosophy: You cannot make an omlette if you don't have an egg in the first place.

Solution 4 - C#

Not sure, but this may be because .Net doesn't knows whether it is predefined class or user-defined. If it is predefined then it can be null(like string which occupies 2 Bytes) but if it is user-defined than we have to create an instance of it so that it knows that this object will occupy this much memory. So therefore it throws error at run-time.

Solution 5 - C#

Good question. The message box is just short of useless. Even if it's buried a mile deep from the references definition, some class or assembly or file or other information would be better than what they currently provide (read: better than nothing).

Your best option is to run it in the debugger with debugging information, and your IDE will break at the offending line (rather clearly demonstrating that useful information is in fact available).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1968030View Question on Stackoverflow
Solution 1 - C#Martin LiversageView Answer on Stackoverflow
Solution 2 - C#romarView Answer on Stackoverflow
Solution 3 - C#Aniket IngeView Answer on Stackoverflow
Solution 4 - C#Oniel TeliesView Answer on Stackoverflow
Solution 5 - C#Rick O'SheaView Answer on Stackoverflow