Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Visual Studio tell me which reference threw a NullReferenceException?

I'm writing unit tests for an MVC web app, and I've been getting null reference exceptions because the mocked-up test objects are only partly initialized. I know which line is throwing the exceptions, and it looks something like this:

return Supervisor.RegistrationInformation.Registrations
    .Any(r =>
        r.RegistrationCountry.IsUSAOrCandada() &&
        (!DatesWorked.Start.HasValue || r.RegistrationDate <= DatesWorked.Start.Value) &&
        (!DatesWorked.End.HasValue || r.RegistrationExpirationDate >= DatesWorked.End.Value) &&
        //...

There are a lot of references in there, and any of them could be the problem. However, NullReferenceException itself doesn't seem to capture which reference blew up. The fact that I'm passing in a lambda presents another challenge: As far as I can tell, I can't step through the lambda during debugging and see which members of r are null.

Is there any way I can do one or both of the following:

  • Have Visual Studio tell me exactly which reference threw the NullReferenceException?
  • Failing that, is there a way to make the debugger step through the lambda expression (or just hover over things to see their values) as it's being evaluated by Any?

I feel like there must be a way to do these things, but I can't seem to find it. I'm on VS2010 Premium, and I have Resharper, VS Power Tools, and a couple other extensions installed. If there's an add-on that does this, I'd be fine with that.

Edit:

As Eric Lippert points out, it's impossible to pinpoint the source of an NR exception when the code has been compiled in Release configuration. I'm only asking about working in debug mode. If Visual Studio (or some extension to VS) can track the source of a reference while debugging, that would answer my question.

Edit 2:

The second question--how to break and step through a lambda--has been answered, but I'd still like to know if there's an automatic way to track down a null reference.

like image 595
Justin Morgan Avatar asked Dec 06 '11 22:12

Justin Morgan


4 Answers

There is not in general a way to do what you want, no. To understand why, think about what is happening when a null reference exception is thrown. Imagine that you are the compiler, and you must emit code to process a call to abc.Def.Ghi.Jkl(), where abc is a local, Def and Ghi are fields of reference type, and Jkl is a method. There is no IL instruction that can do something that complicated; you have to break it down. So you emit code for an equivalent program where everything is much simpler. You emit the program fragment:

temp1 = abc.Def;
temp2 = temp1.Ghi;
temp2.Jkl();

Suppose temp2 is null because Ghi was null. That fact will not be discovered until Jkl is invoked, at which point the thing throwing the exception does not have any knowledge of how temp2 was initialized. That happened long ago, a nanosecond in the past and machine code has no memory of the past; the null reference does not keep a little note on it that says where the null came from, any more than when you say "a = b + c", the resulting number twelve does not keep a note along with it that says "I was the sum of b and c".

like image 52
Eric Lippert Avatar answered Nov 20 '22 02:11

Eric Lippert


This won't solve your entire problem, but it should help:

You can set a breakpoint inside the lambda -- just not in the usual way (clicking in the gutter will breakpoint the containing statement, not the innards of the lambda). You have to put the cursor inside the lambda and hit F9 -- then you'll get a breakpoint inside your lambda.

like image 26
Joe White Avatar answered Nov 20 '22 02:11

Joe White


One solution for your particular problem is to rewrite the lambda in a multiline one that evaluates every condition one by one and returns explicitely. You can then more easily trace through it and find the null reference.

like image 2
Coincoin Avatar answered Nov 20 '22 02:11

Coincoin


If you set a breakpoint here, you should be able to inspect each of the values before the line is executed and the exception is thrown. You just have to methodically look at each dereferenced item until you find the Null one. Visual Studio is very good at this sort of thing.

like image 1
i_am_jorf Avatar answered Nov 20 '22 00:11

i_am_jorf