ArgumentNullException and refactoring


I hate using strings to represent program elements!  One of the big problems is that it hinders automated refactoring.  Strings don’t have any semantic meaning, so refactoring tools don’t know which references to the string need to be updated.

 

While playing with expression trees, a while ago I came up with this:

public static class Argument
{
    public static void NotNull(object value, Expression<Func<Func<object>>> arg)
    {
        if (value == null)
        {
            var body1 = (Expression<Func<object>>)arg.Body;
            var body2 = (MemberExpression)body1.Body;
            throw new ArgumentNullException(body2.Member.Name);
        }

    }
}

 

You can use this for argument validation like this:

static void Main(string[] args)
{
    Argument.NotNull(args, () => () => args);
}

 

This looks a little strange, but has some interesting properties:

  1. There are no strings, which means that refactoring tools “Just Work” and update all references.
  2. The majority of the reflection code happens only in the exception code, which means that this has significantly better performance than my first attempt (which took just an “Expression<Func<object>>”

On the other hand it has some drawbacks too:

  1. The calling side looks a little strange with “() => () =>’”
  2. Using this approach will lead to a LOT of compiler generated display classes to store the parameter references.

I’m not sure I would use this in production code, but it was an interesting exercise to come up with a way of validating parameters that doesn’t involve strings.

 

What do you think?


Comments (4)

  1. int19h says:

    We use a similar trick for our INotifyPropertyChanged implementations for mostly the same reasons (refactoring, plus it’s so easy to mistype a property name when it’s a string, and the compiler doesn’t check).

  2. Jay Bazuzi says:

    If you’re willing to take a small performance hit, you can skip the first ‘value’ argument, and replace ‘value == null’ with ‘arg.Compile()()() == null’.  This results in a cleaner usage / DRY:

    Argument.NotNull(() => () => args);

    The perf hit is the Compile() call.  For me, avoiding the bug where I copy/paste one call to create other calls, and forget to replace one of the parameters is worth the tradeoff most of the time.

    I think I’d keep both as overloads (sharing some implementation).  I’d use the 1-parameter version until performance analysis revealed the bottleneck in my code, and there switch to the other.

    Kevin knows all of this, of course: I’m trying to be useful to the other readers.

  3. Kirill Osenkov says:

    Wouldn’t it be nice if the language "understood" more of it’s own constructs, like it "understands" types and methods (delegates)?

    A method parameter list should be a tuple, and people should be able to not only access values of the tuple, but also the tuple field information. A lot of things would become easier with this – currying, chaining calls (instead of ugly "out" parameters that don’t compose at all, one could just return a tuple).

    Unfortunately, C# wasn’t designed with meta-programming in mind, that’s why we have to resort to ingenious tricks (I admit it, the trick itself is seriously cool, especially given the constraints) to mimic introspection that comes for free in languages like Lisp, Boo or Nemerle.

  4. Markus Hjärne says:

    It would be nice (and much easier than the suggested code) if the compiler would support a nameof operator similar to the typeof operator.

    static void Main(string[] args)

    {

       if (arges == null)

         throw new ArgumentNullException(nameof(args));

    }

    The nameof operator should support as many types of identifiers as possible and return the name of the identifier as a string.