Isn’t it a bit of a pain in the ass to have to spell out the name of an offending method argument when throwing an ArgumentNullException? What about when you have to spell out the name of a method you want to invoke dynamically?

Sounds to me like we’re in the early stages of drafting up a large list of liabilities as far as our software is concerned. Every time you have to personally provide a literal in your code, you’re introducing a potential point of fail that will not be caught by the compiler. Literals reflecting intrinsic program characteristics can also very easily make refactoring dangerous.

Look, I know, but…my hands are tied! That’s just the way it is!

No sir, you are very wrong. Instead of slapping sloppy literals all over our code, we can replace them with programmatic elements that’ll cause compilation failure given any compromise in the correctness of these elements.

What would be really nice is if we could get the results of Reflection without having to use Reflection –

Whoa. Whoa man, hold up. Reflection. Huge performance hit man. Huge.

Relax. Reflection operations are expensive to perform, in comparison with other operations in the BCL. You really need to be using it quite a bit for you to be impacted, however.

Well, in our case, if we did use Reflection to somehow retrieve the names of methods, and perhaps the names of parameters to pass to a validation routine that checks for argument correctness…well that’d certainly add up, wouldn’t it?

Let’s see how we can do all of this using Expression trees instead. Unless we are actively compiling Expression trees during run time, we can essentially bypass all penalties normally associated with Reflection by using Expressions instead. Of course what we do is limited to the very definition of Expressions themselves, in that they are merely representations of code.

Expressing the Name of a Method Parameter

Going back to an earlier example, let’s say we want to throw an ArgumentNullException. Well we want to give the exception the name of the offending parameter. So, how can we do this?

When working with lambda expressions, we have several options when it comes to compile-time. We can either compile the lambda expression as a code delegate, or as, you guessed it, an Expression tree.

Creating Expressions via lambda expressions carries many restrictions along with it. More complex Expression trees require the use of the Expression API, which will result in Expressions being generated at run-time, not compile-time, and this cause a performance hit.

But thankfully, we won’t be dealing with a complicated expression tree.

So, here’s a method we could pass the parameter to in order to get its name:

private string ReadPropertyName<TProp>(Expression<Func<TProp>> expression)
{
    // You may want to add validation logic here that checks if the expression
    // is formed correctly.
    MemberExpression body = (MemberExpression) expression.Body;
    return body.Member.Name;
}

How do we pass the parameter to this method? For compile-time creation of Expressions, we can assign a lambda expression to a variable of type Expression<TDelegate>, an example of that being Expression<Func<T>>. Going forward, we can just pass a lambda expression to the ReadPropertyName method, and we’ll have our Expression.

    public string Method(object arg)
    {
        if (null == arg)
            throw new ArgumentNullException(
                ReadPropertyName(() => arg), Resources.MethodArgumentIsNull);
    }

You now have compile-time safety with the use of the parameter’s name, and all without incurring any sort of performance penalty.

Quite a bit of a mouthful we have there though. We’ll probably be doing lots of checking for null inputs if we have many public methods. Also, we can take advantage of using Expressions in many more places than just passing the names of arguments to validation methods, simply think of anywhere you are currently using a string that refers to some sort of code element. In addition to that, we’ll need to be doing this outside of this class.

So, how can we make this a bit more compact and universal?

Well the best we can do here is simply move the logic in ReadPropertyName and all of the null checking logic to some validation utility class. Validation, especially validation in the sense of checking for a null reference, is a concept that can touch every kind of situation and object. Because this is so universal, it is most certainly not bad design to offload general validation procedures to utility classes.

There’s really no way to avoid the requirement of passing the parameter as a lambda expression. Creating an extension method such as “ToLambdaExpression” or something will fail, since that’ll invariably change the expression so that name of the member is whatever is used in the extension method body.

So, let’s make a new utility method in a validation utility class we can use:

    public static void CheckNullArgument<T>(
        T argument,
        Expression<Func<T>> argumentExpression,
        string messageIfNull)
    {
        // Probably want to add validation code for the expression here.
        MemberExpression memberExpression = (MemberExpression) argumentExpression.Body;

        string argumentName = memberExpression.Member.Name;   

        if (argument.IsDefaultOrNull())
            throw new ArgumentNullException(argumentName, messageIfNull);
    }

The IsDefaultOrNull method call you see near the end is an extension method I wrote that is used when I’m working with an object that could either be a reference or value type, and I’m not aware of which. It simply makes use of the default EqualityComparer for the type.

This would be invoked by:

    public IEnumerable<IResourceReservation> Reserve(ReserveParameters parameters)
    {
        Validation.CheckNullArgument(
            parameters, () => parameters, Resources.NullServiceParameters);
    }

We could even make the validation method more general, or at least offer a more general validation routine alongside the null argument check that would simply run some validation criteria against an object and throw an ArgumentException if it fails.

    public static void CheckArgument<T>(
        T argument,
        Expression<Func<T>> argumentExpression,
        Predicate<T> validationCriteria,
        string messageIfFail)
    {
        // Probably want to add validation code for the expression here.
        MemberExpression memberExpression = (MemberExpression) argumentExpression.Body;

        string argumentName = memberExpression.Member.Name;   

        if (!validationCriteria(argument))
            throw new ArgumentException(messageIfFail, argumentName);
    }

This would be invoked by (let’s say if we want to check if a property named StartDate is greater than the current date):

    public IEnumerable<IResourceReservation> Reserve(ReserveParameters parameters)
    {
        Validation.CheckArgument(
            parameters,
            () => parameters,
            x => x.StartDate > DateTime.Now,
            Resources.BadServiceParameters);
    }

Matt Weber

I'm the founder of Bad Echo LLC, which offers consulting services to clients who need an expert in C#, WPF, Outlook, and other advanced .NET related areas. I enjoy well-designed code, independent thought, and the application of rationality in general. You can reach me at matt@badecho.com.

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
   
© 2012-2013 Matt Weber. All Rights Reserved. Terms of Use.