Search code examples
c#exceptionnullreferenceexceptionargumentnullexception

Should I check if argument is null if I'm going to use it immediately?


I'm so used to check if a method's argument is null (then proceed to throw an exception) that I almost don't even think about it anymore. If the argument is a reference type, it's there:

if(arg == null)
    throw new ArgumentNullException(nameof(arg));

But what if I'm going to use arg immediately? Should I check anyway? I mean, if I don't, the envinroment will throw for me (a NullReferenceException) anyway.

For instance:

public int DoStuff(object o)
{
    return o.GetHashCode();
}

I could write add the null check easily:

public int DoStuff(object o)
{
    if(o == null)
        throw new ArgumentNullException(nameof(o));
    return o.GetHashCode();
}

But in both cases a exception will be thrown (in almost the exact same line, for debugging purpose). The only difference is the type.

The question: On public methods with a single reference type argument, if I'm going to use the argument immediately, should I still check it if it's null?


Solution

  • I suggest checking, because you have two Exception types:

    1. Unexpected NullReferenceException - something went wrong, and you have to debug your own routine
    2. ArgumentNullException - the argument is null, and it's caller that's wrong (and not your code which reacts right)

    throwing ArgumentNullException is kind of contract: I'll do the thing in case argument is correct:

      // An exaggerated example 
      public int DoStuff(SomeObject o) {
        if (o == null)
          throw new ArgumentNullException(nameof(o));
        else if (o.Disposed)
          throw new ArgumentException(nameof(o), "o must not be disposed")  
        else if (o.Id > 100)
          throw new ArgumentOutOfRangeException("Id ...", nameof(o));  
    
        // o meets the contract, we accept it and thus we guarantee the output
    
        return o.SomeMethod();
      }
    

    This kind of validation is typical for public (protected) methods since they're exposed to outer world and can face any argument; however, in case of private method you can omit the contract: any caller is within the class that implements the method.