A better way to handle NullReferenceExceptions in C#
c#, exception
Solution
Firstly: don't do too much in a single statement. If you have huge numbers of dereferencing operations in one line, it's going to be much harder to find the culprit. The Law of Demeter helps with this too - if you've got something like `order.SalesClerk.Manager.Address.Street.Length` then you've got a lot of options to wade through when you get an exception. (I'm not dogmatic about the Law of Demeter, but everything in moderation...)
Secondly: prefer casting over using `as`, unless it's valid for the object to be a different type, which normally involves a null check immediately afterwards. So here:
// What if foo is actually a Control, but we expect it to be String?
string text = foo as string;
// Several lines later
int length = text.Length; // Bang!
Here we'd get a NullReferenceException and eventually trace it back to `text` being null - but then you wouldn't know whether that's because `foo` was null, or because it was an unexpected type. If it should really, really be a `string`, then cast instead:
string text = (string) foo;
Now you'll be able to tell the difference between the two scenarios.
Thirdly: as others have said, validate your data - typically arguments to public and potentially internal APIs. I do this in enough places in Noda Time that I've got a utility class to help me declutter the check. So for example (from `Period`):
internal LocalInstant AddTo(LocalInstant localInstant,
CalendarSystem calendar, int scalar)
{
Preconditions.CheckNotNull(calendar, "calendar");
...
}
You should document what can and can't be null, too.
Problem
I recently had a coding bug where under certain conditions a variable wasn't being initialized and I was getting a `NullReferenceException` . This took a while to debug as I had to find the bits of data that would generate this to recreate it the error as the exception doesn't give the variable name. Obviously I could check every variable before use and throw an informative exception but is there a better (read less coding) way of doing this? Another thought I had was shipping with the `pdb` files so that the error information would contain the code line that caused the error. How do other people avoid / handle this problem? Thanks