tags:

views:

973

answers:

18

Quite often, in programming we get situations where null checks show up in particularly large numbers. I'm talking about things like:

if (doc != null)
{
  if (doc.Element != null)
  {
    ... and so on
  }
  else
    throw new Exception("Element cannot be null");
} else {
  throw new Exception("document cannot be null");
}

Basically, the whole thing turns into an unreadable nightmare, so I'm wondering: is there an easier way to describe what I'm trying to do above? (In addition to null checks, I get things like string.IsNullOrEmpty from time to time.)

Accepted answer: I accepted the answer that has this link because the approach described is innovative, and is precisely what I want. Thanks Shawn!

+2  A: 

That code example is hardly unreadable... You will have to check for nulls when there is a possibility of a variable being null. However, if you want to cut back on this, make sure that methods which return an object never return null and always return a fully valid and constructed object. Have it throw an exception in the case where you had it return null. Returning null or -1 or some other odd convention shouldn't be substituted for error handling.

Zombies
+10  A: 

If you're just going to throw an exception anyway, why not let the language runtime throw it for you?

doc.Element.whatever("foo");

You'll still get a NullPointerException (or whatever it is in C#) with full traceback information.

Greg Hewgill
(1) Makes sense in contexts where the variable being null is an exceptional condition. In some contexts it may be an acceptable program state.(2) Chaining multiple references on one line means you wouldn't know whether it was "doc" or "doc.Element" that is null.
Dave Costa
I agree. This is probably the best option, but it looks like there's a difference in the message that gets returned with the error. Maybe just log the error message and stack trace, instead of using different messages...
Paige Watson
+1 to Dave Costa's comment. Of course I can't vote up a comment... But I agree with his points completely. A NullReferenceException is not the same as an ArgumentNullException.
Troy Howard
+1 because if programmers add a null check for every single reference, applications would end up with more null checks than code.
jdigital
@Troy: you could try { doc.Element.whatever("foo"); } catch (NullPointerException e) { throw new ArgumentNullException(null, e); } :))
Hosam Aly
Umm, it doesn't really work for me because I need to give the user well-formed error messages. In the end, it is Visual Studio that catches my exception, not my own code. I just want it to look nice.
Dmitri Nesteruk
If you happen to call a method of the possibly-null-object, that approach may be ok. But in many cases you store the object (that is, you store a reference to null somewhere) and call a method on it later (maybe in another medthod/class/thread), and you have a hard time finding the bug.
Brian Schimmel
+14  A: 

Push them forward to the beginning of the function, and keep them out of the part of the code that does the work. Like this:

if (doc == null)
    throw new Exception("document cannot be null");
if (doc.Element == null)
    throw new Exception("Element cannot be null");
AndSoOn();
Dan Monego
+1 -- same as my answer :)
Dave Costa
You can even take it a bit further and refactor the huge block of null checks into it's own method.
Troy Howard
NullPointerException perhaps?
Joe Philllips
-1 because these exceptions add no value and don't even help someone debugging. Moreover, throwing class Exception itself is strongly discouraged.
jdigital
agreed. Also.. much better to NOT throw an exception unless it's unexpected behaviour...
Troy Howard
+2  A: 

Seperate (static?) function call:

public static void CheckForNullObject( object Obj, string Message) {
    if(Obj == null){
        throw new Exception(Message);
    }
}

While this wouldn't be the best option, it would be a little more readable.

Paige Watson
It's close to what I want, but I really want a function to test a whole chain, i.e., something like CheckForNullChain(doc|Element|Member|Value)
Dmitri Nesteruk
Then you'll just have the same code as the original, but elsewhere in the class.
Paige Watson
Or you could write some crazy Reflection-based thing that would walk the properties to your desired point. But that's just kind of silly. That ends up being harder to read and understand when you come back to it. Take the simplest route. ;)
Troy Howard
i have a utility class with a series of these (nullCheckString, nullCheckDecimal, etc.) for a data import project. It keeps things neat and it makes sure that I use a robust check and valid return value every time.
Rob Allen
FYI, I use those for DBNulls mostly
Rob Allen
+3  A: 

Perhaps the constructor of a class should only create the object if the properties are initialized to appropriate values? That being said an instance would only be created if it has the minimum number of properties upon creation other than that you could create a Validate(Doc doc) method that would essentially do the same thing, i.e. check the validity of the object.

RandomNoob
+1 -- I like the ValidateObject() idea... or just a property IsValid, or HasValue, or SafeToUse.. ;)
Troy Howard
+4  A: 

You may be interested in the Null Object Pattern.

It has helped me in the past to get rid of null checks in a lot of instances.

Example (C++)

   class IThing
   { 
        public:
          virtual void DoThing() = 0;
   }; 

   class NullThing : public IThing
   { 
        public:
          virtual void DoThing() { /*no-op*/}
   }; 

   class RealThing : public IThing
   { 
        public:
          virtual void DoThing() { /*does something real*/}
   }; 

   int main()
   {
         NullThing theNullInstance; /* often a singleton or static*/
         IThing* thingy = &theNullInstance; /*the null value*/

         // Do stuff that may or may not set  thingy to a RealThing

         thingy->DoThing(); // If is NullThing, does nothing, otherwise does something

         // Can still check for null 
         // If NullThing is a singleton
         if (thingy == &theNullInstance)
         {
              printf("Uhoh, Null thingy!\n"); 
         }
   }
Doug T.
-1 because the solution is more painful than the problem. Wrapping every reference just obfuscates the code.
jdigital
I'd like exceptions thrown, too. But thanks for the example - it does demonstrate a useful pattern.
Dmitri Nesteruk
@Jdigital. I disagree. Though it does not solve the specific problem it is a very easy way to get rid of excessive null checks. A Null implementation of an interface will easily pay itself off in lines of code in a couple of avoided null checks.
Doug T.
This isn't dissimilar from (e.g.) EventArgs.Empty in intent, as far as I can tell.
Greg D
A: 

Do NOT catch exceptions unless you are able to do something intelligent with them.

In this case, your exception handlers add little value over the default -- that is, letting the exceptions propagate back up the call chain.

At the top level(s) of your app/thread, there should always be exception handlers to deal with these uncaught exceptions.

EDIT: Being voted down, I feel misunderstood, maybe I'm too sensitive ;-). The exceptions that the original poster is throwing have no value. They don't help the end user and they don't help the developer.

The top level exception handlers in an application should catch an exception like this and log it. The log should include the stack trace. This tells the developer where the error came from and eliminates many lines of code that really serve no purpose.

IF the exception adds some value, then I'd agree that it is reasonable to throw it. But that isn't the case here. Even worse, once you state that this is a good principle, you'll see many more lines of code checking for null references, to the point that the code will be cluttered with them.

jdigital
He's throwing exceptions here, not catching them. Throwing explicit correctly typed Exceptions is good in all situations.
Troy Howard
And actually it adds a lot over the default. I've seen cases where the null propagates through the code and you don't detect it until (much) later--sometimes in a different thread. It's much better to help out the developer by failing early (and LOUDLY).
Bill K
@Troy, the system will throw an exception. His Throws add no value.
jdigital
@Bill, you might have missed my statement about top level exception handlers, which will eliminate the issue of much later cross thread detection. The problem with many apps is that they omit top level handlers and just allow exceptions to end up "wherever".
jdigital
You must be careful with top level exception handlers. You aren't supposed to catch(Exception e) although many people, including myself, do.
Adam Tegen
@Adam, I suspect that depends on your environment. If you are writing your own app (public static void main) then you should catch Exception because no one else is going to do it for you.
jdigital
+3  A: 

If a typical NullReferenceException will do, don't bother checking and just let the runtime throw it. If you need at add contextual error information, for logging or debugging purposes (or whatever), go ahead and factor your validation out into a different method. I'd still encourage you to throw a NullReferenceException with the original exception nested, in that case.

I've had to do similar things when I've been forced to manually munge through deep XML documents.

In general, I try to enforce null-correctness at interface boundaries in my classes. I can then ignore null checks within my private methods.

Greg D
+2  A: 

If you feel it is unreadable because of the nested ifs, my suggestion would be to rewrite like this:

if (doc == null)
{
  throw new Exception("document cannot be null");
}

if (doc.Element == null)
{
    throw new Exception("Element cannot be null");
}

doc.Element.someMethod()
Dave Costa
I prefer to do this. Especially in the case of loops (continue). This is actually what the compiler renders the logic to anyway.
StingyJack
-1 because how is throwing an explicit exception useful. See Greg's suggestion earlier -- letting the framework throw the exception. The only time you should do this is if you're going to add value, and these throws do not do that.
jdigital
@jdigital -- not a big deal, but the throwing of explicit exceptions wasn't my idea, it was in the original code. I was just showing a different way to structure the code.
Dave Costa
A: 

You could always write:

if (doc == null && doc.Element == null {

}

But you loose the granularity with the solution one post above mine (e.g. seperate messages in Exception).

dotnetdev
For small chains, it could be `if (doc == null || doc.Element == null) throw new ArgumentNullException(doc == null ? "doc" : "doc.Element");`
Hosam Aly
Hosam Aly
Even if you use OR, you will still get an exception. Some languages will evaluate both sides of the statement, even if the left-hand statement is true.
rotard
Dmitri Nesteruk
+2  A: 

Have a look at the "Maybe Monad".

It addresses your desire for a readable way to do verbose Null checks in C#.

Crescent Fresh
A: 

To address the people that advocate allowing the runtime to throw a NullReferenceException:

I started a topic on the subject of whether or not it is a good idea to proactively throw an ArgumentNullException or to let the runtime throw a NullReferenceException. The basic consensus was that it's a good idea to take the proactive approach rather than the NullReferenceException approach. I'm not necessarily saying that they're right and the people who advocate otherwise here are wrong. I'm just saying that the community may disagree with you.

What I would like to point out is that if you're doing a lot of these kinds of checks, chances are good that you're doing something wrong. Either your methods are doing too much or you're passing around too many "tramp" arguments (arguments that serve no purpose other than to be passed to another function). Perhaps you should consider whether you can break your code up more into separate methods or maybe encapsulate some of the arguments into an object.

Jason Baker
Your observation ("...if you're doing a lot of these kinds of checks, you're doing something wrong...") is spot on and points out why "the consensus" is wrong ;-)
jdigital
+2  A: 

There are a couple of options (some have already been mentioned by others), so I'm just adding to the list.

  1. For some types it makes sense to employ a null object. In that case, you have to make sure, that methods never return a simple null, but always return an instance (which may be the null object).

  2. If you want to use the static method as suggested by Paige, you can even turn it into an extension method. You could do something similar to:

     private static void ThrowIfNull(this object o, string message) {
        if (o != null) return;
        throw new ArgumentNullException(message);
     }
    
Brian Rasmussen
You know, I really like this!
Dmitri Nesteruk
+8  A: 

You might be interested in Spec#:

Spec# is a formal language for API contracts, which extends C# with constructs for non-null types, preconditions, postconditions, object invariants, and model programs (behavioral contracts that take the history of the entire run into account).

You can make it the caller's responsibility to make sure the argument is not null. Spec# uses the exclamation mark to denote this:

public static void Clear(int[]! xs) // xs is now a non-null type
{
    for (int i = 0; i < xs.Length; i++)
    {
        xs[i] = 0;
    }
}

Now the Spec# compiler, it will detect the possible null dereferences:

int[] xs = null;
Clear(xs);   // Error: null is not a valid argument

As a side note, you might also want to make sure you're not breaking the Law of Demeter.

Craz
A: 

If you just happen to be using C# consider nullable.

SquidScareMe
+18  A: 

Check out this article: A fluent approach to C# parameter validation

It's written by one of the Paint.NET Developers. He uses extension methods to simplify and clean up null checking code.

Shawn Simon
Could you double-check that URL and/or what SO does to it?
Eric
Wow, this is really cool!
Dmitri Nesteruk
Very nice article; the technique works in any OO language with exceptions. Thanks and +1.
Norman Ramsey
+1  A: 

Contracts are a key element in reducing null-related problems and superflous checks.

There are methods that may/should return null in some cases. If you call a method like this, then you simply have to check. It's best to check as early as possible.

And there are methods which are not allowed to return null. Don't check their return values. Each mehtod is responsible to ensure it fulfills its own contract, so as a caller of that method you don't have to care.

There are tools and language features to help you document and check the correctness of null-checking and contracts. Sorry I can't explain any more because I'm not a C# programmer.

If you want to dive in deeper, I recommend those four questions. They are mostly Java-centric, but almost everything is true for C# as well, and sometimes the answers are even customized to .net and c#.

Brian Schimmel
I have to admit that my answer does not fit your code example very well. But you might find that it is helpful in many other cases.
Brian Schimmel
Thanks, I'll check out those links.
Dmitri Nesteruk
A: 

If you are about to check parameter passed to part of your public API, then you should use "guard clauses" in the very beginning of your method like Dan Monego has wrote. The code will be easy reading if you create or reuse some helper class like Assert with methods like IsNotNull and others (maybe you really need only one of them).

Your code will look like:

Assert.IsNotNull(doc, "document");
Assert.IsNotNull(doc.Element", "Element");

//... and so on

If you are about to check parameter passed to one of your private methods, then you shouldn't have such checks, instead of that you should add a contract (in method documentation or with some special declarations if you are using some tool for that) and always expect that this method will be called with correct parameters.

Dmitriy Matveev