Click here to Skip to main content
15,884,473 members
Articles / Programming Languages / C#

Understanding Expression Trees

Rate me:
Please Sign up or sign in to vote.
4.34/5 (30 votes)
22 Jul 2009Ms-PL3 min read 60.1K   21   15
Expression trees tutorial.

Introduction

C# 3.0 came up with many interesting features including Lambda Expressions, field and collection initializers, anonymous types, type interference, and others. One of them is expression trees – mysterious topic tightly coupled with LINQ.

This article will describe in detail what expression trees are. It will also show you how to construct and how to use them in C#. It will end up with answering several important questions about expression trees – what is so special about them? Why and when to use them? And what is the difference between expression trees and Lambda Expressions?

This article assumes that you have at least a decent knowledge about Lambda Expressions, as well as about LINQ (LINQ to Objects especially).

Expression trees definition

In general, Expression Trees are special kind of binary trees. A binary tree is a tree in which all the nodes contain zero, one, or two children. Why have expression trees been implemented as binary trees? Mainly because binary trees allow you to quickly find what you are looking for. The upper limit of steps necessary to find the required information in binary trees equals to log2N, where N denotes the number of all nodes in a tree.

Let's give the following example careful consideration:

C#
Func<int, int, bool> f = (a, b) => a < b; 

It is a simple declaration of Lambda Expression that takes two numbers as parameters and returns true whenever the first number is less than the second one and false otherwise. Fairly simple. But, we could also write the same logic in an expression tree. What is the difference? Before answering this question, let's take a look at how to create them.

Constructing expression trees

To create an expression tree that refers to the previous example, we have to use the following syntax:

C#
Expression<Func<int, int, bool>> f = (a, b) => a < b; 

Pretty much the same. The only difference is the use of the Expression<T> class. This class is somewhat handy as it contains four interesting properties holding useful information about the underlying expression tree:

  1. Body
  2. NodeType
  3. Parameters
  4. Type

Alternatively, you could also build the same expression tree in another way – step by step:

C#
ParameterExpression par1 = Expression.Parameter(typeof(int), "p1"); 
ParameterExpression par2 = Expression.Parameter(typeof(int), "p2"); 
BinaryExpression expr = Expression.LessThan(par1, par2); 
var f = Expression.Lambda<Func<int, int, bool>>(expr, 
                   new ParameterExpression[] { par1, par2 });

Using expression trees

So far, I have shown that constructing expression trees is more difficult and complex than constructing simple Lambda Expressions. So is the way they are used. To use an expression tree, you must first compile it:

C#
var func = f.Compile();

From now on, you can use as any other function:

C#
var result = func(2,5); 

Pretty much overhead, isn't it? Then, why bother yourself about expression trees if the same goals may be achieved using lambda expressions in a simpler and faster way?

Expression trees purpose

In the previous example, I have shown that the given expression tree must be compiled before it can be used. This is because the expression tree is actually a data structure, not compiled code. Why? Because this code is expected to be used across wire, or – in other words – in other processes (running possibly on other computers). For example, a query in LINQ to SQL constructed on my machine will be send to the database server. The server will construct itself a specific expression, run it, and return the requested values. It is much easier for external data providers to construct an appropriate query based on the expression tree (which is the data structure) than based on the compiled piece of code.

This does not apply to LINQ to Objects, however. In this case, your queries will be run in the same process they were called, and there is no need to create any special data structure to represent your query. This is why in LINQ to Objects, Lambda Expressions may be used. In all other cases, you must rely on expression trees.

Summary

Expression trees are a very interesting concept. At the beginning, it might seem that they simply double up the functionality offered by Lambda Expressions. The difference is noticeable, however, when different kinds of LINQ than LINQ to Objects are used. In such cases, your queries will be send across wire and run in different processes and possibly on different machines. It is a cool idea that makes such scenarios possible, and is very easy and straightforward.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
CEO
Solomon Islands Solomon Islands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
PraiseShort N Sweet Explanation Pin
Shabana Parveen4-May-18 4:17
professionalShabana Parveen4-May-18 4:17 
GeneralMy vote of 2 Pin
Ankita Biswas Bhattacharya19-Mar-14 2:34
Ankita Biswas Bhattacharya19-Mar-14 2:34 
QuestionThanks! Pin
Ghenady4-Feb-14 10:51
Ghenady4-Feb-14 10:51 
GeneralMy vote of 4 Pin
BBC Model B18-Apr-12 23:16
BBC Model B18-Apr-12 23:16 
GeneralMy vote of 1 Pin
Tecfield20-Mar-12 9:30
Tecfield20-Mar-12 9:30 
GeneralMy vote of 1 Pin
Sander Rossel2-Feb-12 10:46
professionalSander Rossel2-Feb-12 10:46 
GeneralMy vote of 2 Pin
computermage13-Nov-11 16:12
computermage13-Nov-11 16:12 
GeneralMy vote of 4 Pin
HC4414-Apr-11 23:15
HC4414-Apr-11 23:15 
GeneralMy vote of 1 Pin
Member 45365623-Oct-10 8:29
Member 45365623-Oct-10 8:29 
GeneralUpto the point. Pin
mittalpa27-Nov-09 17:59
mittalpa27-Nov-09 17:59 
GeneralThanks! Pin
Phan Dung2-Nov-09 20:13
Phan Dung2-Nov-09 20:13 
GeneralMy vote of 1 Pin
Member 61796049-Aug-09 23:01
Member 61796049-Aug-09 23:01 
GeneralGreat! Pin
Yoyosch22-Jul-09 7:59
Yoyosch22-Jul-09 7:59 
GeneralMy vote of 1 Pin
coresoftlab22-Jul-09 3:51
coresoftlab22-Jul-09 3:51 
GeneralMy vote of 1 Pin
Juergen Gutsch22-Jul-09 2:44
Juergen Gutsch22-Jul-09 2:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.