15
\$\begingroup\$

I am using this code in a lot of places:

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

But I think this is not DRY. The only difference here is ParameterName. Is it ok to use these lines everywhere, or is there a way to make it DRY?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This is where you wish you had C macros \$\endgroup\$
    – Demi
    Mar 24, 2014 at 22:34
  • \$\begingroup\$ @Demetri no, it really isn't! Even if you did, there's nothing to stop you using the C preprocessor on C# files. \$\endgroup\$
    – MattDavey
    Mar 27, 2014 at 11:21

5 Answers 5

10
\$\begingroup\$

Looks pretty DRY to me. :) You can use expressions to somewhat reduce the amount of code you need to write:

    public static void ThrowIfNull(Expression<Func<object>> expression)
    {
        var res = expression.Compile();
        if (res.Invoke() == null)
        {
            var lambda = (LambdaExpression) expression;
            var member = (MemberExpression) lambda.Body;
            throw new ArgumentNullException(member.Member.Name);
        }
    }

    public void SomeMethod(object someParameter)
    {
        ThrowIfNull(() => someParameter);
    }

but frankly i'd go with Re-sharper templates (or VS code snippets) instead.

Edit: A quick test on my machine shows, that on average it takes about 0.22 milliseconds per call to execute ThrowIfNull 1000000 times with different (not null) arguments. With first call being ~20 times slower (perhaps repeated compilation is optimized and/or cached in some way, tho i am not competent enough on that subject to make any claims). Is it slower then one equality check? Well, obviously. But it is still unlikely to become any kind of a bottleneck in real life scenario, unless overused. As i said, however, i would not use it. The original code looks clear and short enough to me, even shorter, when templated. So i always go with simple explicit null check.

\$\endgroup\$
10
  • \$\begingroup\$ You mean the condition checking is DRY itself. Yes, I have found these lines a lot in ASP.NET MVC 5 source which led me to think this is not bed. \$\endgroup\$ Mar 24, 2014 at 11:02
  • 8
    \$\begingroup\$ Won't that be quite slow, compiling an expression each time? A null check should be cheap so you can do lots of them - compiling code for each one seems like it might slow things down a lot. \$\endgroup\$
    – MrKWatkins
    Mar 24, 2014 at 12:58
  • \$\begingroup\$ Why are you using an expression for this? Seems a little overkill to me, unless of course I'm missing something blindingly obvious. \$\endgroup\$
    – Joe
    Mar 24, 2014 at 17:57
  • \$\begingroup\$ @MrKWatkins, slow compared to what? To the original solution? Yes, of course. See my edit. \$\endgroup\$
    – Nikita B
    Mar 25, 2014 at 5:03
  • 1
    \$\begingroup\$ @NikitaBrizhak If you did want to tie the name in with an expression then I'd probably pass the value and the expression. Check the value for null (which wouldn't involve compilation) and only then parse the expression to get the parameter name. \$\endgroup\$
    – MrKWatkins
    Mar 25, 2014 at 10:02
13
\$\begingroup\$

Google Guava's Precondition class contains good patterns for this problem. For example, the checkNotNull method is the following:

T checkNotNull(T reference, String errorMessageTemplate, Object... errorMessageArgs)

Usage:

checkNotNull(parameter, "parameter cannot be null");

Note its return value. If the value is not null it returns the referencce, so you can use it in the following way:

public MyClass(MyObject dependency) {
    this.dependency = checkNotNull(dependency, "dependency cannot be null");
}

It also supports error message templates with %s.

Although it's a Java library, you can implement the same methods in C# too, they are really simple.

See also: Preconditions Explained

\$\endgroup\$
4
  • \$\begingroup\$ +1 for mentioning preconditions. This seems like a good time to introduce code contracts (and the DbC principle in general). \$\endgroup\$
    – MattDavey
    Mar 24, 2014 at 11:17
  • \$\begingroup\$ I am using C#.. \$\endgroup\$ Mar 24, 2014 at 11:29
  • \$\begingroup\$ @user960567: "Although it's a Java library, you can implement the same methods in C# too, they are really simple." \$\endgroup\$
    – palacsint
    Mar 24, 2014 at 11:35
  • 2
    \$\begingroup\$ As of Java 7, you could use the built-in Objects.requireNotNull method. But then again... this is a C# question :) \$\endgroup\$ Mar 24, 2014 at 12:49
10
\$\begingroup\$

If you just want a short syntax, you could use Code Contracts.

Either

Contract.Requires( x != null );

or

Contract.Requires<ArgumentNullException>( x != null, "x" )

depending on whether the exact exception type is important to you. There is also some configuration to be done, depending on if you want these checks only for debug, or also for release.

I should point out, however, that Code Contracts are really about much more than simple argument checks, and it has its own pros and cons. More information here.

\$\endgroup\$
2
  • \$\begingroup\$ Note that Contract.Requires( does not necessarily throw any exception. \$\endgroup\$
    – Martin Ba
    Feb 23, 2015 at 13:50
  • \$\begingroup\$ Could you elaborate on that? \$\endgroup\$
    – MEMark
    Feb 23, 2015 at 14:48
8
\$\begingroup\$

I would go for a generic extension method for this:

public static void ThrowIfNull<T>(this T parameter, string name) where T : class
{
    if (data == null)
        throw new ArgumentNullException(name);
}

This way, you can call

Parameter.ThrowIfNull("Name");

If you're calling this on a property, you could use CallerMemberNameAttribute, this won't work from a method though.

\$\endgroup\$
3
  • \$\begingroup\$ If you have access to the new C# 6.0 features, you can could use the new nameof(...) operator if (data == null) throw new ArgumentNullException(nameof(data)); The compiler will catch any parameter name mismatchs which may occur if you rename a parameter. \$\endgroup\$ Sep 15, 2015 at 8:23
  • 1
    \$\begingroup\$ @JoeKing would nameof(data) just come back with "data"? I don't think it will cascade down. I could be wrong. \$\endgroup\$
    – Joe
    Sep 15, 2015 at 11:57
  • \$\begingroup\$ Yes, it really only helps in the case where you rename a parameter. On a side note, the nameof() operator can also come in very handy when implementing the INotifyPropertyChanged interface, as property renaming has to be one of the main sources of data binding bugs. \$\endgroup\$ Sep 15, 2015 at 13:39
5
\$\begingroup\$

You could try to extract it to a method, but you'd still have to call it for every parameter and you will lose the information, what the parameter's name is....

CheckNull(object ParameterName){
   if(parameterName == null){
      throw new ArgumentNullException("some param was null, no clue which...");
   }
}
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.