105

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?

  • 2
    When this happens, rewrite the line it happened on so it checks each possible result for null first - then you'll know exactly what it was. Either that, or have Visual Studio's amazing debugger attached, which breaks the instant an exception occurs and lets you see what is null :) – Patashu Feb 09 '13 at 11:24
  • that's not his question – bas Feb 09 '13 at 11:24
  • Duplicate at programmers http://programmers.stackexchange.com/questions/130250/why-object-reference-not-set-to-an-instance-of-an-object-doesnt-tell-us-which – nemesv Feb 09 '13 at 11:25
  • There are many ways to check the error in dot net may be you dont know all those........one of them is "error list". When you debug the code automatically it will show the line where your getting problem. – andy Feb 09 '13 at 11:26
  • 5
    Not really, he simply asks why the .NET framework does not help the programmer to show **which** object is null. I guess it's the performance penalty (you'd need reflection). but I am not sure either. – bas Feb 09 '13 at 11:27
  • 1
    @bas: While that is true, the question is a bit misleading in that it should be asking about a "part of an expression", not an "object". That also explains why mere reflection won't help, but some extensive debug information will be required. – O. R. Mapper Feb 09 '13 at 11:29
  • 4
    Still I am curious for the answer. It's kind off similar to .net exceptions not helping to point out **which** key does not exist in a dictionary. Also, I don't understand the devotes on the question. – bas Feb 09 '13 at 11:30
  • Thanks for all down vote –  Feb 09 '13 at 11:31
  • +1 for what it's worth – bas Feb 09 '13 at 11:31
  • .NET is a framework. how should it tell something? Do you mean visual studio? – VladL Feb 09 '13 at 11:45
  • 13
    Terminology please: An object is never null. An _object reference_ might be though. But an object reference is just a location in memory - how would it help you, unless you have a debugger attached anyway? – Oskar Berggren Feb 09 '13 at 11:47
  • @VladL: Visual Studio doesn't really have all that much to do with exception or debugger messages. .NET can be used perfectly fine without Visual Studio. The crucial point is that the `NullPointerException` and its message is supplied by code found in the .NET Framework itself, therefore asking about the capabilities of the .NET Framework is correct here. – O. R. Mapper Feb 09 '13 at 11:47
  • Could it be through overhead of the CLR to find the name of the variable which is null? – Johannes Egger Feb 09 '13 at 11:50
  • @Jasd: It's not necessarily a single variable; it can also be a more complex expression. E.g. `myTuples[4].Item1`. – O. R. Mapper Feb 09 '13 at 11:52
  • 100% duplicate http://stackoverflow.com/questions/779091/what-does-object-reference-not-set-to-an-instance-of-an-object-mean – spajce Feb 09 '13 at 12:10
  • 1
    @spajce: The only connection between that question and this one is that they are both referring to the same exception. The questions are entirely different. – O. R. Mapper Feb 09 '13 at 12:34
  • Haha, another cool question. +1 – Afshin Mehrabani Feb 09 '13 at 14:25
  • "It's kind off similar to .net exceptions not helping to point out which key does not exist in a dictionary." -- Actually it's not at all similar. if a key isn't in a dictionary, the key is in hand and can be included in an exception. In the case of a null reference, the only thing in hand is null. – Jim Balter May 05 '15 at 01:54

5 Answers5

172

(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.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • exactly my point when I asked O.R.Mapper where he is planning to get the source code from – Aniket Inge Feb 09 '13 at 11:54
  • 5
    Line numbers and source file names aren't stored in the IL code itself, either, or are they? Yet, they can be made available for debugging. – O. R. Mapper Feb 09 '13 at 12:00
  • @O.R.Mapper: They are stored in the symbols (.PDB files). – Martin Liversage Feb 09 '13 at 12:00
  • 4
    @MartinLiversage: Exactly. So the question boils down to: Why isn't there sufficient info stored in the symbols files that also tells what expression in the code was evaluated to `null`. – O. R. Mapper Feb 09 '13 at 12:02
  • 1
    @O.R.Mapper: Symbol files are used during debugging by the debugger and are not used at all by the .NET virtual machine. And in a release build optimizations will change the generated code making it hard to exactly correlate IL instructions with source code. Symbols are not required to execute a .NET application. – Martin Liversage Feb 09 '13 at 12:04
  • 2
    @MartinLiversage: Symbol files are accessible in a way so that upon an exception, along with the exception message, the source file and line number can be displayed in the output of the debugger. So, the question is, what's the reason for not including some more info on what exactly returned `null` - note that the OP doesn't claim he or she wants to know that for release builds, as well, debug builds may be sufficient. – O. R. Mapper Feb 09 '13 at 12:06
  • 3
    Hmm, and we should't forget that it's not even the IL that actually executes, but rather native code built from it at runtime. – Oskar Berggren Feb 09 '13 at 12:07
  • @OskarBerggren: I'm speculating here, but I would expect the `callvirt` opcode to translate to native machine code that performs a check for 0 instead of relying of whatever exception mechanism the underlying hardware and operating system has (e.g. no general protection fault is raised). – Martin Liversage Feb 09 '13 at 12:11
  • @O.R.Mapper: Symbol files is a debugger feature and does not work well with a release build. Symbols correlates IL opcodes with source file lines and gives you human readable names for methods and variables but it does not tell you anything about why a particular value on the stack is the null reference. I'm not saying it is impossible but I would think that it is a vary hard problem to solve in the general case. And any production application will not have symbols anyway. – Martin Liversage Feb 09 '13 at 12:16
  • 2
    @MartinLiversage: No-one in this question claims we want this perfectly supported for release builds. Anyway, I don't quite see the problem in correlating the IL opcode that uses an object reference (that may turn out to be `null`) with the source file line and column that returned that object reference. – O. R. Mapper Feb 09 '13 at 12:21
  • 1
    @O. R. Mapper the reason why there isn't sufficient info to say what expression evaluated to null is because... no one has coded it yet! Think about how difficult it would be, how many corner cases you'd need to write, all the testing to make sure it would never screw up and crash .NET, etc. for so little gain. – Patashu Feb 09 '13 at 12:47
  • @Patashu: I currently cannot imagine any corner cases, because there's always an expression of some sorts that returns `null`, but if "it is not implemented" is the only reason that we can find here (unless anyone knows the reason for the actual design decision), then that should be added as an answer. And the risk of crashing .NET is ... a bit far-fetched for something that "is not used at all by the .NET virtual machine", as others have pointed out above. – O. R. Mapper Feb 09 '13 at 13:12
  • 2
    @MartinLiversage: actually, AFAIK the implementation of `NullReferenceException` does rely on a hardware fault being raised. See this question for more details: [Why is memory access in the lowest address space (non-null though) reported as NullReferenceException by .NET?](http://stackoverflow.com/questions/7940492/why-is-memory-access-in-the-lowest-address-space-non-null-though-reported-as-n) – Daniel Pryden Feb 09 '13 at 23:15
  • @O. R. Mapper: As an example, the use of async, yield and so on produces vastly different compiler-created code than the code the programmer actually wrote. – Patashu Feb 10 '13 at 00:23
  • 1
    @Patashu: Can you provide an actual example where that would be problematic? A `yield someObject.SomeProperty.SomeNestedProperty.SomeValue;` statement is presumeably compiled to something like `current = someObject.SomeProperty.SomeNestedProperty.SomeValue;` in the `MoveNext()` method, right? Would the single steps of this expression be resolved any differently than outside of a `yield` statement? – O. R. Mapper Feb 10 '13 at 10:02
  • @O. R. Mapper Async/awaiter state machines is a good example - if you've ever read about how async is implemented in C#, the simple looking method gets translated into a huge, complex state machine - and for the compiler generated expressions/variables to then be meaningful, it has to store enough information to do the reverse operation and get back to the source code. In any case, someone has to actually WRITE it. – Patashu Feb 10 '13 at 10:09
  • I understand why the runtime doesn't tell me which reference is null, but couldn't it tell me which method was called that caused the error? In your example, if the exception told me that the Length method was called, that would be very helpful information. – Michael Levy Mar 23 '15 at 21:31
  • 1
    Actually, given your example above, doesn't the runtime have enough information to provide an error message like "A null reference attempted to call the Length method of the class System.String". That would be a more helpful message and it seems like it is possible for the runtime to provide that detail. – Michael Levy Mar 23 '15 at 21:42
  • "couldn't it tell me which method was called that caused the error?" -- The debugger provides the file name and line number where the call occurs. That's all you need. – Jim Balter May 05 '15 at 01:59
  • I'm curious if the expression "Program.GetString()" shown in the VS Exception Detail popup is available somewhere in the exception object? – AaronLS Nov 22 '21 at 22:58
9

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!

romar
  • 804
  • 7
  • 17
  • 2
    I suspect the OP is looking for the expression in the source code that returns null, not the object. I've added a respective comment to the question and hope he or she will clear things up. If my suspicion is correct, the OP would expect something like `Object reference obtained from AnyObject.GetANullObject() not set to an instance of an object.` as the error message. – O. R. Mapper Feb 09 '13 at 11:51
  • 1
    @O.R.Mapper I agree. I would have just put my "answer" in a comment to the OP, if I had enough reputation points to add a comment! – romar Feb 09 '13 at 12:24
  • 1
    "a null reference attempted to call the ToString() method of the Class XYZ" would be more helpful than what we get now. – Michael Levy Mar 23 '15 at 21:39
  • The most helpful thing would be a stack trace showing, at each call level, exactly what line, in what file, resulted in the error. Oh, wait ... that's what it does now! – Jim Balter May 05 '15 at 02:02
1

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.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • 3
    that's not an answer either :) – bas Feb 09 '13 at 11:42
  • How do you get the reference if it doesn't exist? @Bas – Aniket Inge Feb 09 '13 at 11:42
  • 4
    "Well, that's upto engineers at Microsoft to answer.". So let them shed a light on this instead of stating the obvious – bas Feb 09 '13 at 11:43
  • @bas we can decide what is logical at the very least. Logically the object does not exist. How will you catch it with an exception and then print out the name of the object? It just does not exist. Not even on stack.. – Aniket Inge Feb 09 '13 at 11:45
  • so the answer is that's is virtually impossible to point out which object has a nullreference? That's an answer too. I am not stating that I know, I just like the question :). +1 for all the effort :p – bas Feb 09 '13 at 11:49
  • @Aniket: I suspect the OP is looking for the *expression* in the source code that returns `null`, not the *object*. I've added a respective comment to the question and hope he or she will clear things up. – O. R. Mapper Feb 09 '13 at 11:49
  • @O.R.Mapper and where from is he planning to get the expression? – Aniket Inge Feb 09 '13 at 11:52
  • @Aniket: Runtime debugging info? It's not like that were impossible, it just seems like the current implementation doesn't do it, and the OP is simply asking why not. – O. R. Mapper Feb 09 '13 at 11:56
  • It is not really the object which is null but the reference. The reference does exist. – Brian Rasmussen Mar 07 '13 at 21:58
1

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.

Oniel Telies
  • 155
  • 2
  • 14
-2

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).

Rick O'Shea
  • 1,410
  • 19
  • 15