LINQ Expressions

This post is part of the series. In case you missed other articles, they are listed below:

  1. #1: LINQ Expressions (current)
  2. #2: Extending LINQ Expressions

It has been quite some time from my last blog post. With getting used to new job and new found love for mountain hiking I didn’t have as much time as I would have liked for writing. However, now I have a topic that I really like since I worked with LINQ expressions for some time and I find them really powerful. In this post I will explain what LINQ expressions are and where they are used.

Chance is you may have used LINQ expressions already, you were just not aware of it. If you ever used MVC Razor engine with view model binding or Entity Framework, you were passing LINQ lambda expressions as arguments to various methods. However from programmer’s point of view those arguments were indistinguishable from normal lambdas and this is the reason why you may have never noticed the difference. So let us look into what the difference is and where expression trees are used.

What exactly are expression trees

Expression tree is nothing more than tree structure where each node represents some kind of expression. Expression can represent many .NET constructs, for example:

Root class for every expression is System.Linq.Expressions.Expression. This class also contains factory methods for all built-in expressions. While you can use those methods to create expression tress, you usually don’t have to because compiler can do that automatically for us. For example consider the following code:

1
2
Func<int, int> f = x => x + 1;
f(1); // will return 2

This is definition of lambda function which accepts int and returns increment. Compiler will produce function which can then be executed by supplying parameters.

Consider now this code:

1
2
Expression<Func<int, int>> fexp = x => x + 1;
fexp(1); // ERROR: will not compile

The only thing that is different is type declaration. But since we specified that variable fexp is expression, compiler will transparently emit code for creation of corresponding expression tree. Above declaration would be equivalent to the following code:

1
2
3
4
5
6
7
8
var p = Expression.Parameter(typeof(int), "x");
var fexp = Expression.Lambda(
  Expression.AddChecked(
    p
    Expression.Constant(1)
  ),
  p
);

This is quite a mouthful for just a simple lambda expression which increments parameter. Now imagine what you would have to write if you have a more complex expression.

What are expression trees used for

What can we do with lambda expressions that we cannot do with lambdas? If you take lambda f once this is compiled it is essentially a black box. You can supply lambda with arguments to get result, but there is no way to know at runtime what this lambda does. In contrast if you take lambda expression fexp which is tree structure representing expression ‘x => x + 1’, you can visit nodes at runtime and see that it will return increment of argument. In fact visiting logic is already provided for you by System.Linq.Expressions.ExpressionVisitor. You just need to extend this abstract class and override methods for those expression types you are interested in.

Lambda expression has another feature: after inspection you can dynamically compile it to normal lambda which can be executed. For example:

1
2
3
Expression<Func<int, int>> fexp = x => x + 1;
var fcompiled = (Func<int, int>)fexp.Compile();
fcompiled(1); // will return 2

Keep in mind though that compilation is not cheap and you should cache result.

You could also transform given expression tree to new expression tree, which you then wrap in lambda and dynamically compile to executable code. There really are a lot of possibilities what you can do. But let us look how Razor engine and Entity Framework utilizes expression trees.

How expression trees are used in Razor engine

If you ever used MVC and Razor engine you are probably familiar with the following construct:

1
@Html.TextBoxFor(m => m.Field1)

While first argument looks like normal lambda, if you look at the definition of method TextBoxFor you would see that it is generic method which accepts lambda expression which accepts model as input and returns something. With expression trees, Razor engine can achieve following goals:

This way the only thing that developer has to specify is property accessor, everything else will be done for him automatically. Razor engine will of course also compile and cache compiled expressions for retrieving model value, which is used when rendering page, so performance should not suffer.

Note about new tag helpers feature: while you don’t see explicit lambdas anymore, engine still uses expressions in the background. This means that this code:

1
<input asp-for="Field1" />

is equivalent to above code, and underlying lambda expression will be the same.

What about Entity Framework

Entity Framework translates expression trees to equivalent SQL query which will return expected data from database. There are two different mechanisms at work:

Conclusion

Expression trees are really a powerful and useful feature which can be used in many different situations. I hope that expressions are no longer a mystery to you and you are already thinking where you could use them. In the next post I will explore how to create custom expressions and how infrastructure handles them.

Thanks for reading.

Comments