tags:

views:

1165

answers:

12

Where do you check if an object that you are passing to a method is null or not?

Should an object need to be tested before calling a method? or within the method that is using the argument?

public class Program
{
    public static void Main(string[] args)
    {
        // Check if person is null here? or within PrintAge?

        PrintAge(new Person { Age = 1 });
    }

    private static void PrintAge(Person person)
    {
        // check if person is null here?

        Console.WriteLine("Age = {0}", person.Age);
    }
}

public class Person
{
    public int Age { get; set; }
}

Having a "null" check in both classes seem to be too much redundant code.

[EDIT]: What would be an dis/advantage of checking for null within a caller or a callee?

[EDIT2]: I just ran into Defensive Programming and it seems like it advocates checking null within a callee. I wonder if this is a widely accepted practice.

+2  A: 

You mean checking in both methods? I'd check in PrintAge for sure and if it makes sense within Main as well. I don't think there is a definite answer in general. It depends :-)

Miha Markic
+4  A: 

I would say that checking it n PrintAge seemed to make more sense as that is fulfiling the contract for the routine. You could, of course, replace the null checks with Debug.Assert() code to check at test time, but not at release time.

Martin Randall
+1  A: 

What would you want to do, if instance is null?

I think it depends on the API you provide & define contract (the way .net framework classes do). Having said that, you need not do a check for null (in main), if the method defines what is expected outcome in case of null reference passed to it.

shahkalpesh
Actually it depends on many cases what I should do when an object is null. If I check for a null in the callee, then I would thrown an exception or do nothing. Within a called function, I would do the same.
Sung Meister
What I mean is lets assume it is a method you let external users call, what would you want to do in the method being called, if the value passed is null?
shahkalpesh
@shahkalpesh: I would sometimes want to throw an exception or just return an empty list depending on what a method does(whether it is a Get/Set method)
Sung Meister
+1  A: 

I normally let my null checks be controlled by my expectations; if I expect something to be null or am unsure of it, I add a check. Otherwise I don't. Nulllpointer exceptions are among the easiest problems to track, so excessive sprinkling of checks bloats code. In the specific example I'd check nothing, because it's intutitive it's not null.

krosenvold
So basically, your practice is that, it varies according to current situation?
Sung Meister
Yes. I try to express my expectations, even through such checks.
krosenvold
A: 

Redundant code isn't the most elegant but its safe.

This depends on who your intended user is, if its you then your in control of how everything is used and the checks are only necessary if your unsure of what the state of your variables will be.

If your making this for someone else to use then null checks are probably a good idea. Even if you just throw a NullPointerException its better to fast fail.

Patrick Auld
+1  A: 

There is only one occasion that a constructor can return null [new() on a Nullable<T>] - so the calling code doesn't need to check.

The callee probably should check; throwing an ArgumentNullException if it was null. In .NET 4.0 this will be better served by code contracts. But not yet ;-p

Marc Gravell
What I am still having trouble understanding is "why" the "calling code doesn't need to check" and dump the null check on the callee.
Sung Meister
Because it cannot possibly (with the code as originally presented) be null.
Marc Gravell
+2  A: 

You've got nothing to check in Main - you're using the new operator which never returns null (except for Nullable<T>).

It would be entirely reasonable to check in PrintAge, particularly if it were made public. (For private APIs it's less important to do argument checking, but it can still be very useful.)

if (person == null)
{
    throw new ArgumentNullException("person");
}

These days in C# 3.0 I usually use an extension method for this.

Jon Skeet
+2  A: 

You can design a method to work with valid objects only.

That means you are expect to receive valid objects ( not null in your case ).
That means you don't know how to react and what to do with invalid objects:

  • returning silently from the function is not a solution;
  • throwing an exception will mean you move responsibility to the upper methods where they can check the value already before passing to you.

So if your method don't know exactly how to handle invalid object and the method won't follow additional logic in the invalid case you should put

Debug.Assert( Person );

at the PrintAge begin and this will force you to make checks upper by call stack.

The lower function in hierarchy is the less checks it should do. The following is disadvantages of doing checks in the functions that do the work.

  • Function that is doing actual work has to be as clear as possible without mass of ifs
  • Function will be called more then many times
  • Such function can call such functions and they can call such functions again. Each of them will perform the same validation
Mykola Golubyev
The problem with Debug.Assert is that unless you explicitly include the DEBUG symbol in your release build, your code will behave differently in development vs in production - not good. Production is the time you want to *really* make sure you don't keep going with bad data :)
Jon Skeet
Assert in Debug will force you to make checks before calling this PrintAge
Mykola Golubyev
+Marked as Answer: "Each of them will perform the same validation"
Sung Meister
If this code is not supported by unit testing and if it's in some obscure part of the flow you might not spot it and false security of Assert can bite you back!
dr. evil
@Slough:False security of Assert? What is that suppose to mean? Don't you control the way your project builds? Unit tests. Does placing if all around the code cross out unit tests need? I am so sick of all this 'if just in case' and that was started because of some 'if' in the lower level function.
Mykola Golubyev
A: 

Definitely check in PrintAge, it's a right place to check. It can be redundant but won't hurt anyone unless you execute it 1000 times per second. (Depending on the check throw an exception or fix it if you can)

Other check is depend on your actual flow, in this example you don't have a flow so I can't comment on that bit. But generally consider your parameters as tainted.

dr. evil
Why would checking for nullability within "PrintAge" would be a "right place to check"? I was initially concerned about redundant code being everywhere...
Sung Meister
I think it'd be right place because if you call PrintAge from somewhere else it'd still function correctly (or at least better).
dr. evil
But obviously it can cause redundancy when you have multiple PrintAge similar functions, and well there is not too much to do about it.
dr. evil
+4  A: 

If you design a library, there will be methods exposed to the outer world. You should check the incoming data in this methods. No checks are required in methods that you do not expose, because only your code calls them and its logic should handle all cases you accepted in the exposed method called.

                    --------------------------
                   |                          |
                   |         Library          |
                   |                          |
 -------        ---------        ----------   |
|       |      |         |      |          |  |
| Outer |      | Library |      | Library  |  |
|       | ===> | Entry   | ===> | Backend/ |  |
| World |      | Method  |      | Helpers  |  |
|       |      |         |      |          |  |
 -------        ---------        ----------   |
                   |                          |
                   |                          |
                    --------------------------

If you have accepted the supplied data in the entry method, you should perform the requested action and return the exspected result, that is handle all remaining cases.

UPDATE

To clearify the situation inside the library. There might be null checks, but only because of the logic, not because of parameter validation. There are two possibilties for the location of null checks inside the library. The first one if the called method knows how to handle null values.

private CallingMethod()
{
   CalledMethod(someData);
}

private CalledMethod(Object parameter)
{
   if (parameter == null)
   {
      // Do something
   }
   else
   {
      // Do something else
   }
}

And the second situation if you call a method that cannot handle null values.

private CallingMethod()
{
   if (someData == null)
   {
      // Do the work myself or call another method
   }
   else
   {
      CalledMethod(someData);
   }
}

private CalledMethod(Object parameter)
{
   // Do something
}

The whole idea is to reject cases you cannot handle immideatly and handle all remaining cases properly. If the input is not valid you throw an exception. This forces the library caller to supply only valid values and does not allow the caller to continue execution with meaningless return values (besides the caller shallows the exception an continues).

Daniel Brückner
So within the "Library Backend/Helpers", there is no "null" check in both caller and callee? Am I understanding your point correctly?
Sung Meister
There might be null checks, but only if required by the actual logic. There are no null checks just to validate parameters.
Daniel Brückner
A: 

PrintAge should be a method on Person, not a static taking a Person as parameter. No check needed.

Checking for null values makes the code unnecessarily complex. Structure your code so as to limit (or eliminate) the occasions where null is a possible value, and you'll have much fewer checks to write.

Morendil
"Checking for null values makes the code unnecessarily complex" <- within a caller or a callee?
Sung Meister
Both places. My preference is to do away with the need to check, at all.
Morendil
+1  A: 

As I understand your question it is more general than illustrated by your example. My preferences are as follows:

  • All publicly accessible methods must check for NULL input and throw exceptions as appropriate. So if you're building a framework for others to use, code defensively.
  • Private methods may omit the NULL check if you know that this is done elsewhere or that arguments will never be NULL, but in general I prefer the explicit ArgumentNullException to NullRefereceException.

Brad Abrams has some more input here: http://blogs.msdn.com/brada/archive/2004/07/11/180315.aspx

Brian Rasmussen
@Brian: Yes, my question was a bit too general.
Sung Meister