views:

137

answers:

5

Recently I'm developing a software that parses and displays XML information from a website. Simple enough right?

I'm getting LOADS of NullReferenceExceptions. For example, this method:

private void SetUserFriends(List<Friend> list)
{
    int x = 40;
    int y = 3;

    if (list != null)
    {
        foreach (Friend friend in list)
        {
            FriendControl control = new FriendControl();
            control.ID = friend.ID;
            control.URL = friend.URL;
            control.SetID(friend.ID);
            control.SetName(friend.Name);
            control.SetImage(friend.Photo);

            control.Location = new Point(x, y);
            panel2.Controls.Add(control);

            y = y + control.Height + 4;
        } 
    }
}

I had to wrap an ugly as sin If around the actual foreach loop in order to prevent an exception.

I feel I'm just putting bandaids on a flat tire instead of actually fixing the problem. Is there any way I can tackle this problem? Maybe a book I should read regarding programming patterns or what not?

Really, I'm lost. I'm probably asking the wrong questions.

+4  A: 

I'm probably going to get downvoted by the "no multiple exit" crowd but I usually handle that with a simple check right at the beginning of the method:

if (list == null || list.Count == 0) return;

this specifies the exit conditions and then you don't need to worry about multiple levels of indentation in your method. This only works if you can afford to swallow the fact that your list is null or empty - which can happen in some cases.

But I agree with codeka, in that you need to look at the calling code and work out if you can improve it from there.

Darko Z
This approach *might* work for this specific case, but in general it leads to very subtle bugs. Most of the time we cannot reasonably infer what the caller intended by passing in `null`, so it is safest to abort with an exception.
Rex M
It should be documented whether or not a method accepts null, and (ideally) what it does if this pre-condition is not met. I agree with @Rex that silent returns can often hurt debugging.
Matthew Flaschen
I fully agree with you both, but there are cases where it can be useful
Darko Z
If the code shouldn't accept a null, then silently failing would be bad and the right answer would be to throw an exception. However, it may well be that a null is an acceptable input. It depends, so let's not be hasty here.
Steven Sudit
@Steven in this case, the OP is complaining about all the problems he's gotten himself into by letting nulls through. So... :)
Rex M
@Rex: Point taken. Having it throw on null would force them to look at the call stack and understand how a null got through. Having said that, we don't want to give the false impression that throwing is the only reasonable response to a null. To give a silly example, imagine if we applied this dogmatically to `String.IsNullOrEmpty`. ;-)
Steven Sudit
+12  A: 

It sounds as if you're unsure what to do if you receive bad parameters in your methods. There's nothing inherently wrong with what you're doing now, but the more common pattern is to check parameters in the head of your method, throwing an exception if they're not what you're expecting:

if (list == null)
{
    throw new ArgumentNullException(list);
}

This is a common defensive programming pattern - check to make sure that the data you're provided passes basic sanity checks.

Now, if you're calling this method explicitly yourself, and you're finding this method receiving a null list parameter when you're not expecting it, it's time to look at the logic of the calling method. Myself, I prefer to pass an empty list when I have no elements, as opposed to null, to avoid special cases such as this.

Michael Petrotta
+1 If you do this consistently, you'll learn by pain how to write code that avoids unintentional nulls.
Rex M
+1 for defensive programming
Darko Z
A: 

I would return early (or throw an InvalidArgumentException early) when given invalid input.

For example:

private void SetUserFriends(List<Friend> list) 
{ 
    if (list == null) 
        return;

    /* Do stuff */
}

Alternatively you can use the general null coalescing pattern:

private void SetUserFriends(List<Friend> list) 
{ 
    list = list ?? new List<Friend>();

    /* Do Stuff */
}
Graphain
The null coalescing suggestion is a little ridiculous for this scenario, though.
Dan Tao
Returning early and throwing are *extremely* different approaches. Which do you recommend?
Rex M
Uhm, if you're going to throw an exception, the right one would be `ArgumentNullException`, as Michael's example showed.
Steven Sudit
@Dan: Agreed. It makes no sense to allocate an empty list just to do nothing with it.
Steven Sudit
@Dan Agreed, but the OP did ask how you generally deal with it and I just wanted to give them an idea. @Rex, in some ways they aren't that different (they stop the method doing its thing), but its highly contextual. If you come to a counter and forgot to bring anything to purchase I don't have to throw you out of my store (I can just "not process"). If you give me a cheque that bounces it might be time to bring this to someone's attention.
Graphain
+1  A: 

As well as throwing ArgumentNullException exceptions there's also something called the "Null Obejct Pattern" which you can use if you want to be passing around a null, to indicate, for example, that something doesn't exist, but don't want to have to explicitly check for nulls. Essentially it's a stub class that implements the same interface, but its methods are usually either empty or return just enough to make them comple. http://en.wikipedia.org/wiki/Null_Object_pattern

Also useful for value types that can't easily express their non existence, by not being able to be null.

Spike
Interesting, but I'm not sure if it applies here, as the closest thing to the null object pattern here would be keeping an empty list around. The other issue, which I pointed out elsewhere, is that this method should probably accept an IEnumerable instead of a List.
Steven Sudit
True, but he mentioned that this is merely one example of his "LOADS of NullReferenceExceptions". It might be the right solution for some of his others. For this one I'd throw the exception as well.
Spike
My impression here is that this is less a matter of forgetting to check for null and more a matter of not having any idea why it was null in the first place. The null object pattern's purpose is to avoid the null checks, but it won't provide any insight into the deeper issue here. Exceptions would, however, because they'd curb the propagation of nulls, making it easier to follow the stack trace to where a null snuck in.
Steven Sudit
+2  A: 

It seems like defensive programming and parameter validation is what you're looking for.

As others have said, simple parameter validation would work for you:

if (list == null)
    throw new ArgumentNullException("list");

Alternatively, if you tire of constantly writing checks like this for each parameter, you could check out one of the many open source .NET precondition enforcement libraries. I am fond of CuttingEdge.Conditions.

That way, you can use something like this:

Condition.Requires(list, "list").IsNotNull();

However, setting up a precondition like either of the above will just specify that your method does not accept nulls. Your problem will still exist in that you are passing nulls into the method! To fix that, you will have to examine what is calling your methods, and working out why null objects are being passed in.

Joviee
+1 for the focus on root cause.
Steven Sudit
And +1 for referencing CuttingEdge.Conditions ;-)
Steven