Some days ago I’ve had an interesting technical discussion with a colleague of mine regarding the possibility of implementing Guard classes with Expressions in C#. Such a class enables easy argument checking in form of (technical) preconditions on method entry. Thereby the checking logic is encapsulated in the Guard class.
One method of such a Guard
class could be AssertNotNull()
which checks, if a given method argument equals null
and if true throws an ArgumentNullException
. By the use of Expressions the parameter to check can be given to AssertNotNull()
in a very elegant way:
public void MyMethod(SomeType elem) { Guard.AssertNotNull(() => elem); // actual method logic }
Through evaluation of the Expression
the AssertNotNull()
method is able to extract both the name and value of the argument. Thus there’s no necessity to provide both as parameters to AssertNotNull()
. Moreover you do not need to provide the argument name as string
.
Value by compilation
It’s very easy to extract the argument value through compilation and invocation of the Expression
. Hence this solution is often taken by developers who work with Expressions in this way. The following snippet shows this implementation:
public static class Guard { public static void AssertNotNull<T>(Expression<Func<T>> selector) { T value = selector.Compile().Invoke(); if (value == null) { string name = ((MemberExpression)selector.Body).Member.Name; throw new ArgumentNullException(name); } } }
Value by evaluation
In the conversation with my colleague we caught the point that the extraction of the argument value from an Expression
is even possible without performing the costly compilation. This is enabled by converting the Expression
into a ConstantExpression
, from which we can catch the value by executing GetValue()
on a FieldInfo
instance:
public static class Guard { public static void AssertNotNull<T>(Expression<Func<T>> selector) { var memberSelector = (MemberExpression)selector.Body; var constantSelector = (ConstantExpression)memberSelector.Expression; object value = ((FieldInfo)memberSelector.Member) .GetValue(constantSelector.Value); if (value == null) { string name = ((MemberExpression)selector.Body).Member.Name; throw new ArgumentNullException(name); } } }
This doesn’t look very spectacular on first sight. The code is more complicated and it’s necessary to provide a variable in the Expression
. Properties and data hierarchies don’t work with this solution, but this shouldn’t be a problem when checking argument values against null
. Of course with a more sophisticated solution (iterative/recursive evaluation of the Expression
tree) you can enable such scenarios, but this is out of scope of this blog post…
Looking at the execution times
So what’s the point of the second solution? It’s simple: compilation is much more time-intensive! In a little runtime test I’ve compared both solutions. A call of AssertNotNull()
with a valid argument (!= null
) over 10.000 iterations resulted in the following execution times:
Please note the immensive time difference! The compiled solution takes more than 53 seconds, while the evaluation takes less than 0,35 seconds. This makes a time factor of more than 156, by which the evaluated solution is faster than the compiled approach.
Conclusion
When handling with Expressions you should take the execution time into account! Once a method is executed inside of a loop and you follow defensive programming and check method parameters at every place, an argument check can become an important time factor. When possible you should favor evaluation over compilation of Expressions.
Have you considered caching the compilation results?
Great post, found it very useful and educational.
Any chance you could post an update of the method to handle hierarchies and properties?
Would be much appreciated, thanks!