次の方法で共有


Expression Tree Basics

Newcomers to LINQ often find expression trees difficult to grasp. In this post I hope to show that the subject is not quite as difficult as it might appear at first. Any reader who has an intermediate level understanding of LINQ should find the material in this post easy to grasp.

An expression tree provides a method of translating executable code into data. This can be very valuable if you want to modify or transform code before executing it. In particular, it can be useful if you want to transform C# code such as a LINQ query expression into code that operates on another process, such as a SQL database.

But I'm getting ahead of myself. By the end of this post you will find it easy to understand why it is helpful to translate code into data. First I need to provide a little background. Let's start by seeing the relatively simple syntax for creating an expression tree.

The Syntax for an Expression Tree

Consider the following very simple lambda expression:

 Func<int, int, int> function = (a,b) => a + b;
 This statement consists of three sections.
  1.  A declaration: Func<int, int, int> function
    
  2.  An equals operator: = 
    
  3.  A lambda expression: (a,b) => a + b;
    

The variable function points at raw executable code that knows how to add two numbers. The lambda expression shown in step three above is a short hand way of writing the following method:

 public int function(int a, int b)
{
  return a + b;
}

One can call either the method shown above, or the lambda expression like this:

 int c = function(3, 5);

After the function is called, the variable c will be set equal to 3 + 5, which is 8.

The delegate type Func shown above in the declaration found in step one is declared for us in the System namespace:

 public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);

This code looks complicated, but it is used here to help us declare the variable function, which is set equal to a very simple lambda expression that adds two numbers together. Even if you don't understand delegates and generic functions, it should still be clear that this is a way of declaring a variable that references executable code. In this case it points at very simple executable code.

Translating Code into Data

In the previous section, you saw how to declare a variable that points at raw executable code. Expression trees are not executable code, they are a form of data structure. So how does one translate the raw code found in an expression into an expression tree? How does one translate code into data?

LINQ provides a simple syntax for translating code into a data structure called an expression tree. The first step is to add a using statement to introduce the Linq.Expressions namespace:

 using System.Linq.Expressions;

Now we can create an expression tree:

 Expression<Func<int, int, int>> expression = (a,b) => a + b;

The identical lambda expression shown in the previous example is converted into an expression tree declared to be of type Expression<T>. The identifier expression is not executable code; it is a data structure called an expression tree.

The samples that ship with Visual Studio 2008 include a program called the ExpressionTreeVisualizer. It can be used to visualize an expression tree. In Figure 01 you can see a screen shot of a dialog that displays the expression tree for the simple Expression statement shown above. Notice that the lambda expression is displayed at the top of the dialog, and its constituent parts are displayed below it in a TreeView control.

ExpressionTree

Figure 01: The ExpressionTreeVisualizer sample that ships with the VS 2008 C# Samples creates a symbolic rendering of the expression tree.

Writing Code to Explore an Expression Tree

Our simple example is an Expression<TDelegate>. There are four properties in the Expression<TDelegate> class:

  • Body: Retrieve the body of the expression.
  • Parameters: Retrieve the parameters of the lambda expression.
  • NodeType: Gets the ExpressionType for some node in the tree. This is an enumeration of 45 different values, representing all the different possible types of expression nodes, such as those that return constants, those that return parameters, those that decide whether one value is less than another (<), those that decide if one is greater than another (>), those that add values together (+), etc.
  • Type: Gets the static type of the expression. In this case, the expression is of type Func<int, int, int>.

If we collapse the nodes of the tree shown in Figure 1, the four properties of the Expression<TDelegate> class are clearly visible.

ExpressionTreeProperties

Figure 02: By collapsing the nodes of the expression tree, you can easily see the four main properties of the Expression<TDelegate> class.

You can use these properties to start exploring the expression tree. For instance, you can find out the names of the parameters passed to it:

 Console.WriteLine("Param 1: {0}, Param 2: {1}", expression.Parameters[0], expression.Parameters[1]);

This code prints out the values a and b:

Param 1: a, Param 2: b

It should be easy to locate these values in the ParameterExpression nodes shown in Figure 01.

The following code lets us explore the Body of the expression, which in this case is (a + b):

 BinaryExpression body = (BinaryExpression)expression.Body;
ParameterExpression left = (ParameterExpression)body.Left;
ParameterExpression right = (ParameterExpression)body.Right;

 Console.WriteLine(expression.Body);
Console.WriteLine(" The left part of the expression: " +
  "{0}{4} The NodeType: {1}{4} The right part: {2}{4} The Type: {3}{4}",
  left.Name, body.NodeType, right.Name, body.Type, Environment.NewLine);

This code yields the following output:

(a + b)
  The left part of the expression: a
  The NodeType: Add
  The right part of the expression: b
  The Type: System.Int32

Again, you should find it fairly easy to locate this information in the Body node shown at the top of Figure 01.

By exploring the expression tree, we are able to analyze the parts of the expression and discover its components. You can see that all the elements of our expression have been represented as nodes of a data structure. The expression tree is code converted into data.

Compiling an Expression: Converting Data back into Code

If we can convert code into data, then we ought to be able to convert the data back into code. Here is the simple code that asks the compiler to convert an expression tree into executable code:

 int result = expression.Compile()(3, 5);
Console.WriteLine(result);

This code would print out the value 8, the same value as the simple lambda function we declared at the start of this section.

IQueryable<T> and Expression Trees

Now that you have at least an abstract conceptual understanding of an expression tree, it is time to loop back and understand the key role that it plays in LINQ, and particularly in LINQ to SQL. Take a moment to consider this canonical LINQ to SQL query expression:

 var query = from c in db.Customers
            where c.City == "Nantes"
            select new { c.City, c.CompanyName };

As you probably know, the variable query that is returned by this LINQ expression is of type IQueryable. Here is the declaration of IQueryable:

 public interface IQueryable : IEnumerable
{
  Type ElementType { get; }
  Expression Expression { get; }
  IQueryProvider Provider { get; }
}

As you can see, IQueryable contains a property of type Expression, this is the base type from which most variants of Expression<T> are derived. It is designed to hold the expression tree associated with an instance of IQueryable. It is a data structure equivalent to the executable code found in a query expression.

Take a moment to consider the image shown in Figure 03. You will probably need to double-click on it so you can pop up a full sized version of the image. This is the visualization of the expression tree for the query expression shown at the beginning of this section of the post. The ExpressionTreeVisualizer sample was used to create this image, just as I used that sample to create the visualization of the lambda based expression tree shown in Figure 01.

LinqToSqlExpressionTree01

Figure 03: The complex expression tree generated by the simple LINQ to SQL query expression shown above. (Click the image to see the full picture.)

Why Convert a LINQ to SQL Query Expression into an Expression Tree?

You have learned that an expression tree is a data structure that represents executable code. But so far we have not answered the central question of why one would want to make such a conversion. This is the question we asked at the beginning of this post, and it is now time to answer it.

A LINQ to SQL query is not executed inside your C# program. Instead, it is translated into SQL, sent across a wire, and executed on a database server. In other words, the following code is never actually executed inside your program:

 var query = from c in db.Customers
            where c.City == "Nantes"
            select new { c.City, c.CompanyName };

It is first translated into the following SQL statement and then executed on a server:

 SELECT [t0].[City], [t0].[CompanyName]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[City] = @p0

The code found in a query expression has to be translated into a SQL query that can be sent to another process as a string. In this case that process happens to be a SQL server database. It is obviously going to be much easier to translate a data structure such as an expression tree into SQL than it is to translate raw IL or executable code into SQL. To exaggerate the difficulty of the problem somewhat, just imagine trying to translate a series of zeros and ones into SQL!

When it is time to translate your query expression into SQL, the expression tree representing your query is taken apart and analyzed, just as we took apart our simple lambda expression tree in the previous section. Granted, the algorithm for parsing the LINQ to SQL expression tree is much more sophisticated than the one we used, but the principle is the same. Once it has analyzed the parts of the expression tree, then LINQ mulls them over and decides the best way to write a SQL statement that will return the requested data.

Expression trees were created in order to make the task of converting code such as a query expression into a string that can be passed to some other process and executed there. It is that simple. There is no great mystery here, no magic wand that needs to be waved. One simply takes code, converts it into data, and then analyzes the data to find the constituent parts that will be translated into a string that can be passed to another process.

Because the query comes to the compiler encapsulated in such an abstract data structure, the compiler is free to interpret it in almost any way it wants. It is not forced to execute the query in a particular order, or in a particular way. Instead, it can analyze the expression tree, discover what you want done, and then decide how to do it. At least in theory, it has the freedom to consider any number of factors, such as the current network traffic, the load on the database, the current results sets it has available, etc. In practice LINQ to SQL does not consider all these factors, but it is free in theory to do pretty much what it wants. Furthermore, one could pass this expression tree to some custom code you write by hand which could analyze it and translate it into something very different from what is produced by LINQ to SQL.

IQueryable<T> and IEnumerable<T>

As you probably know, the query expressions found in LINQ to Objects return IEnumerable<T> rather than IQueryable<T>. Why does LINQ to Objects use IEnumerable<T> and LINQ to SQL use IQueryable<T>?

Here is the declaration for IEnumerable<T>:

 public interface IEnumerable<T> : IEnumerable
{
   IEnumerator<T> GetEnumerator();
}

As you can see, IEnumerable<T> does not contain a field of type Expression. This points to a fundamental difference between LINQ to Objects and LINQ to SQL. The latter makes heavy use of expression trees, but LINQ to Objects uses them rarely.

Why are expression trees not a standard part of LINQ to Objects? Though the answer may or may not come to you instantly, it should make sense to you once you hear it.

Consider this simple LINQ to Objects query expression:

 List<int> list = new List<int>() { 1, 2, 3 };

var query = from number in list
            where number < 3
            select number;

This LINQ query returns the numbers from our list that are smaller than three; that is, it returns the numbers 1 and 2. Clearly it is not necessary to translate this query into a string that can be passed to another process in order to get the proper answer. Instead, one can convert the query expression directly into .NET code that can be executed. There is no need to translate it into a string or perform any other complex operation on it.

Though this is a bit of a generalization and in practice the lines may be blurred a bit in particular cases, overall the rules are fairly simple:

  • If code can be executed in process then the job can be done with the simple type called IEnumerable<T>
  • If you need to translate a query expression into a string that will be passed to another process, then use IQueryable<T> and expression trees.

Projects like LINQ to Amazon that need to translate query expressions into web service calls that execute out of process will typically make use of IQueryable<T> and expression trees. LINQ to Amazon converts its query expressions into data that a web service can pass to another process that might not even be written in C#. When translating C# code into something that can be passed to a web service the abstractions inherent in an expression tree are very useful. Code that will execute in process, however, can frequently get by without expression trees. The following query, for instance, uses IEnumerable<T> because it calls into the .NET reflection API which is hosted in process:

 var query = from method in typeof(System.Linq.Enumerable).GetMethods()
                       orderby method.Name
                       group method by method.Name into g
                       select new { Name = g.Key, Overloads = g.Count() };

Summary

This post covered a few basic facts about expression trees. These data structures expose and delineate the parts of an expression by translating code into data. At least on the conceptual level, expression trees are quite simple to understand. They take an executable expression and capture its parts in a tree-like data structure. For instance, we examined this simple expression:

(a,b) => a + b;

By exploring the tree derived from this expression you saw the basis for the algorithm used to create the tree shown in Figure 01.

You also saw that expression trees play an especially important role in LINQ to SQL. In particular, they are the data abstraction that is used to capture the logic held in a LINQ to SQL query expression. This data is parsed and analyzed so that a SQL statement can be derived from it and sent to the server.

LINQ makes querying a first class citizen of the C# language that is both type checked and IntelliSense aware. Code of that is type checked and IntelliSense aware must use a true C# syntax that can be directly converted into executable code just as any other C# code be translated and executed. Expression trees make it relatively easy to convert that executable code into SQL statements that can be passed to a server.

Queries that return IEnumerable<T> rather than IQueryable<T> typically do not use expression trees. As a general rule, one can say that LINQ queries that execute in process do not need expression trees while code that executes out of process can make good use of the abstractions inherent in an expression tree.

Download the source.

See also this post on Using the Expression Tree Visualizer.

kick it on DotNetKicks.com

Comments

  • Anonymous
    January 30, 2008
    You've been kicked (a good thing) - Trackback from DotNetKicks.com

  • Anonymous
    January 31, 2008
    This seems a good place to point out/ask about something I noticed back in Beta2, and have verified is still true. Curiously the dispatch overhead calling a delegate produced with Expression.Compile appears to be less than half of the overhead in calling a delegate produced either from a lambda expression or simply pointing at a static method. This is entirely counter-intuative to me.  I can provide the benchmark code if desired, but it isn't anything tricky.

  • Anonymous
    January 31, 2008
    Blake, Okay, that sounds interesting. I also have to agree that it sounds a bit counter-intuitive. Can you show us some code or tell us a bit more about what you are doing to get those results? Thanks.

  • Charlie
  • Anonymous
    January 31, 2008
    Thanks.  I'll email the whole file if you like, but the most relevant bits are short enough to include here: static long Add(long a, int b) { return a + b; } ... Func<long, int, long> AddSD = Add; Func<long, int, long> AddAD = (a, b) => a + b; Expression<Func<long, int, long>> AddExp = (a, b) => a + b; Func<long, int, long> AddDD = AddExp.Compile(); ... stopwatch.Start(); for(var i = 0; i < data.Length; ++i) total = AddDD(total, data[i]); stopwatch.Stop(); Console.WriteLine("Dynamic Delegate: value = {0}, ticks = {1}, {2:P}", total, stopwatch.ElapsedTicks, (double)stopwatch.ElapsedTicks / baseTicks); ... And I get results like these: Static Method: value = 2251799780130816, ticks = 1427409, 100.00 % Static Delegate: value = 2251799780130816, ticks = 2554450, 178.96 % Anonymous Delegate: value = 2251799780130816, ticks = 2451449, 171.74 % Dynamic Delegate: value = 2251799780130816, ticks = 1768117, 123.87 % Colour me puzzled.

  • Anonymous
    January 31, 2008
    I can be reached at blake at bcdev dot com, if that isn't enough to reproduce the results.

  • Anonymous
    February 03, 2008
    Great post.... LINQ ROCKS!!!!!!

  • Anonymous
    February 03, 2008
    It started an email Mohamed Hossam (AKA, Bashmohandes) sent to my company's local office here in Egypt

  • Anonymous
    February 10, 2008
    Hi, I used the Dynamic Query API in order to embed code in XAML... Have a look... http://marlongrech.wordpress.com/2008/02/10/embed-code-in-xaml/ Great JOB you guys!!!!! Regards

  • Anonymous
    February 13, 2008
    The Visual Studio 2008 CSharp samples include several valuable tools that LINQ developers can use to

  • Anonymous
    February 13, 2008
    The Visual Studio 2008 CSharp samples include several valuable tools that LINQ developers can use to

  • Anonymous
    February 13, 2008
    Is It Possible To Use The Same Ideas Of LINQ In Expression Trees In Converting String To LINQ - Ex. Sql2LINQ or A Custom Language Converter To LINQ Expressions. It Seems So Powerful! Great Article.

  • Anonymous
    February 17, 2008
    The comment has been removed

  • Anonymous
    February 17, 2008
    The comment has been removed

  • Anonymous
    February 18, 2008
    This is awesome Charlie, thanks a bunch bro. btw, the trail ahead looks groovy.

  • Anonymous
    April 22, 2008
    Charlie, any chance you'll be responding to Blake Coverett's question about the counter-intuitiveness of his profiling results? Great article though!  Thank you.

  • Anonymous
    May 02, 2008
    Isaac, take a look at the LINQ Dynamic Query Library. Here's a nice blog post on it by Scott Guthrie: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

  • Anonymous
    May 02, 2008
    Eye On .NET is periodical listing series for .NET(Blogs, Articles, Media, Events and Announcing) I hope

  • Anonymous
    June 10, 2008
    Nice post, your clear writing makes this easy to understand

  • Anonymous
    June 18, 2008
    I have just started exploring Expression tree. The article is nice to get good understanding of the concept.

  • Anonymous
    June 19, 2008
    Hi Charlie, Since it helped me a lot, I refer to your blog post at http://dotbert.blogspot.com/2008/06/lambda-expression-trees.html. Greetings, Bert

  • Anonymous
    July 01, 2008
    you're right, but of course there is also a counter-argument, which is that one should only expose interfaces on a "need-to-know" basis, and "just seeing what is going on" does not constitute a need to know.

  • Anonymous
    July 14, 2008
    On the performance of the Express Tree, if we are going to take the evalation of the Func and/or Expression Tree into the consideration, by refactor the code as follows: using System; using System.Collections.Generic; using System.Linq; using System.Text; // using System.Diagnostics; using System.Threading; using System.Linq.Expressions; namespace Performance {    class Program    {        static long Add(long a, int b) { return a + b; }        static void Main(string[] args)        {            int[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,                           11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ,                           21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ,                           31, 32, 33, 34, 35, 36, 37, 38, 39, 40 ,                           41, 42, 43, 44, 45, 46, 47, 48, 49, 50 ,                           51, 52, 53, 54, 55, 56, 57, 58, 59, 60 ,                           61, 62, 63, 64, 65, 66, 67, 68, 69, 70 ,                           71, 72, 73, 74, 75, 76, 77, 78, 79, 80 ,                           81, 82, 83, 84, 85, 86, 87, 88, 89, 90 ,                           91, 92, 93, 94, 95, 96, 97, 98, 99, 100,                           101, 102, 103, 104, 105, 106, 107, 108, 109, 110 ,                           111, 112, 113, 114, 115, 116, 117, 118, 119, 120 ,                           121, 122, 123, 124, 125, 126, 127, 128, 129, 130 ,                           131, 132, 133, 134, 135, 136, 137, 138, 139, 140 ,                           141, 142, 143, 144, 145, 146, 147, 148, 149, 150 ,                           151, 152, 153, 154, 155, 156, 157, 158, 159, 160 ,                           161, 162, 163, 164, 165, 166, 167, 168, 169, 170 ,                           171, 172, 173, 174, 175, 176, 177, 178, 179, 180 ,                           181, 182, 183, 184, 185, 186, 187, 188, 189, 190 ,                           191, 192, 193, 194, 195, 196, 197, 198, 199, 200                         };            long normFactor = RunStaticMethod(data);            RunStaticDelegate(data, normFactor);            RunAnonymousDelegate(data, normFactor);            RunDynamicDelegate(data, normFactor);            Console.ReadLine();        }        static long RunStaticMethod(int[] data)        {            long total = 0;            Stopwatch stopwatch = new Stopwatch();            stopwatch.Start();            // Call the Static Method directly            for (var i = 0; i < data.Length; ++i) total = Add(total, data[i]);            stopwatch.Stop();            double baseTicks = stopwatch.ElapsedTicks;            Console.WriteLine("Static Method      : value = {0}, ticks = {1}, {2:P}", total, stopwatch.ElapsedTicks, (double)stopwatch.ElapsedTicks / baseTicks);            return stopwatch.ElapsedTicks;        }        static void RunStaticDelegate(int[] data, long normalizedFactor)        {            long total = 0;            Stopwatch stopwatch = new Stopwatch();            stopwatch.Start();            //Static Delegate            Func<long, int, long> AddSD = Add;            //stopwatch.Start();            for (var i = 0; i < data.Length; ++i) total = AddSD(total, data[i]);            stopwatch.Stop();            double baseTicks = normalizedFactor;            Console.WriteLine("Static Delegate    : value = {0}, ticks = {1}, {2:P}", total, stopwatch.ElapsedTicks, (double)stopwatch.ElapsedTicks / baseTicks);        }        static void RunAnonymousDelegate(int[] data, long normalizedFactor)        {            long total = 0;            Stopwatch stopwatch = new Stopwatch();            stopwatch.Start();            // Anonymous Delegate            Func<long, int, long> AddAD = (a, b) => a + b;            //stopwatch.Start();            for (var i = 0; i < data.Length; ++i) total = AddAD(total, data[i]);            stopwatch.Stop();            double baseTicks = normalizedFactor;            Console.WriteLine("Anonymous Delegate : value = {0}, ticks = {1}, {2:P}", total, stopwatch.ElapsedTicks, (double)stopwatch.ElapsedTicks / baseTicks);        }        static void RunDynamicDelegate(int[] data, long normalizedFactor)        {            long total = 0;            Stopwatch stopwatch = new Stopwatch();            stopwatch.Start();            // The following two statements are used together            Expression<Func<long, int, long>> AddExp = (a, b) => a + b;            Func<long, int, long> AddDD = AddExp.Compile();            //stopwatch.Start();            for (var i = 0; i < data.Length; ++i) total = AddDD(total, data[i]); //Speedy DD            stopwatch.Stop();            double baseTicks = normalizedFactor;            Console.WriteLine("Dynamic Delegate   : value = {0}, ticks = {1}, {2:P}", total, stopwatch.ElapsedTicks, (double)stopwatch.ElapsedTicks / baseTicks);        }    } } The outcome indicates that the Expression Tree is slowest. The point is that the code will get executed sooner or later. Perhaps, we should take that time into our consideration. And here is the comparison: ============================ When Stopwatch is triggered AFTER the Func and/or Expression Tree evaluation: Static Method      : value = 20100, ticks = 434069, 100.00 % Static Delegate    : value = 20100, ticks = 11713, 2.70 % Anonymous Delegate : value = 20100, ticks = 410176, 94.50 % Dynamic Delegate   : value = 20100, ticks = 9426, 2.17 % .VS. When Stopwatch is triggered BEFORE the Func and/or Expression Tree evaluation: Static Method      : value = 20100, ticks = 434928, 100.00 % Static Delegate    : value = 20100, ticks = 13183, 3.03 % Anonymous Delegate : value = 20100, ticks = 620347, 142.63 % Dynamic Delegate   : value = 20100, ticks = 14994281, 3,447.53 %

  • Anonymous
    August 28, 2008
    StaticStringDictionary - Fast Switching with LINQ revisited

  • Anonymous
    August 28, 2008
    The comment has been removed

  • Anonymous
    September 26, 2008
    Somchai misses the point of my question and benchmark entirely.  Apart from Yes, creating delegates and compiling/JIT'ing expression trees has an overhead, but that's not what I found unexpected.  The odd thing is the speed of dispatch of the resulting calls after they are JIT'd.  Unfortunately I haven't heard anything back from Charlie on this.

  • Anonymous
    February 15, 2009
    Lors des techdays 2009, je suis allé voir la session “ Programmation dynamique ” de Mitsu Furuta et Simon

  • Anonymous
    February 16, 2009
    This is a great post. Thanks for a good learning.

  • Anonymous
    June 14, 2009
    Thanks for this entry. It really explains part of the DLR to me in a better way.

  • Anonymous
    June 20, 2009
    אז בפוסט הקודם ראינו שלמעשה אין ב - Runtime טיפוס dynamic, וכל מה שאנחנו משימים לתוך dynamic עובר להיות

  • Anonymous
    August 05, 2009
    npoBIS  <a href="http://rdrsmmanfghc.com/">rdrsmmanfghc</a>, [url=http://zlpfeeucnkcr.com/]zlpfeeucnkcr[/url], [link=http://ibhrffvvyfvr.com/]ibhrffvvyfvr[/link], http://jqmmkzbtfuuv.com/

  • Anonymous
    September 04, 2009
    Expression Tree Explained in plain language. One of the best blog post I have ever read.

  • Anonymous
    September 17, 2009
    Thank you for this! You have made the complex very simple to understand, which is a rare thing!

  • Anonymous
    October 03, 2009
    Hi, Is it possible convert string to Expression?For the code is: public void testExp(Func<T,object> func) {...} ... string exp="x=>x.name"; testExp(SOME_FUNCTION(exp)); Dose there exist the function(SOME_FUNCTION) I used above?

  • Anonymous
    November 26, 2009
    Very Good blog clarifying the basic concepts really well

  • Anonymous
    January 14, 2010
    I wish a concept of blogging tech info would exactly as you did, thanks a million.

  • Anonymous
    January 14, 2010
    Thanks Raul, Shobz and others. I'm glad this helped.

  • Anonymous
    January 14, 2010
    Guys, has you ever heard about http://en.wikipedia.org/wiki/Abstract_syntax_tree if yes, then why calling it 'expression tree'?

  • Anonymous
    January 15, 2010
    Igor, I usually think of a syntax tree as being a textual, or abstract, version of code, while an expression tree is code. There is a one to one correspondence between the elements in an expression tree and the elements of a computer language: it maps out all the details, and in fact it compiles and runs. A syntax tree, as I understand it, would not compile, but represents a somewhat simplified version of the code in a program. Just as pseudo code is not the same thing as real code, a syntax tree is not the same thing as real code. But an expression tree is real code. Perhaps someone else can step in and explain this in more precise terms, but hopefully this makes some sense to you.

  • Charlie
  • Anonymous
    March 05, 2010
    I had translate this article to chinese. 我已将此文章翻译成中文: http://www.cnblogs.com/tianfan/archive/2010/03/05/expression-tree-basics.html

  • Anonymous
    March 29, 2010
    Great article to start with Expression tree.

  • Anonymous
    April 08, 2010
    Great article to understand LINQ. The comparison between the static and dynamic delegates gives greater awareness to use expressions even in LINQ to Objects

  • Anonymous
    May 12, 2010
    Great post about expression trees. Check out my site http://www.njection.net to find how you can build expression trees using configuration files.

  • Anonymous
    May 25, 2010
    Good!))) Thank you) <a href="0bet.livejournal.com/.../a>

  • Anonymous
    June 09, 2010
    Excellent explanation on Expression Trees and why they are useful. Thanks.

  • Anonymous
    August 05, 2010
    That's a nice article. Btw, i would be very interested to know the answer to Blake's question on performance.

  • Anonymous
    August 28, 2010
    Great article, thank you.  Loved the explanation on IQueryable vs IEnumerable as well.

  • Anonymous
    September 26, 2010
    Great post for a newbie!!

  • Anonymous
    November 23, 2010
    Great article; where you made the complex thing very simple to understand for a newbie by your clear writing capability and great understanding about this. Thank you very much.

  • Anonymous
    December 14, 2010
    Never hurts to be thanked once more. Great article, wish I had found this first! Thank you

  • Anonymous
    December 23, 2010
    the screen shot shows "London" as constant, but the code fragment shows "Nantes"?

  • Anonymous
    January 17, 2011
    Very helpful for LINQ beginners. Thank you

  • Anonymous
    January 27, 2011
    Great explanation, made complex concept so easy!

  • Anonymous
    February 28, 2011
    I read explainations for expression trees in a book, msdn and various online articles/blogs.  This is by far the clearest explaination of them all.  Thank you. Norman

  • Anonymous
    November 13, 2011
    i  got it now !with out magic,complexisity.

  • Anonymous
    February 09, 2012
    Dude this is awesome, I owe you a beer!

  • Anonymous
    May 14, 2012
    I have surfed lots of websites to undertsand use and basics of ExpressionTrees. But as far my search this is the best post i encountered. Thanks for sharing such a clear and understandable post.

  • Anonymous
    June 18, 2012
    Thanks for the greate article, I read more than 10 articles about the utilization of Expression Tree but this gave me the perfect explanation about it. Thanks again

  • Anonymous
    October 17, 2012
    Very nice article, makes it easy to understand

  • Anonymous
    August 07, 2013
    This the best post i have ever seen regarding Expression Tree and  Lambda Expressions. I have one doubt here pls clarify. If i take the case of Linq to SQL then whether the translation of expression tree to equivalent sql happens inside the C# program itself or it happens at the other process i.e. at sql server? I am asking this question because in case someone needs to write a linq provider for mysql then he must know that effort will be required at .NET CLR side or at both .net CLR and Mysql engine side(where a expression tree parser for mysql might have to be written as well) Also please post a series for debugging lambda expressions/trees as well to make our life easy :-)

  • Anonymous
    October 22, 2013
    Hey how deep you know this complicated stuff?. Thank you very much for clear cut specification of such a very dangerous topic .You are rocking.

  • Anonymous
    October 29, 2013
    Awesome!

  • Anonymous
    January 09, 2014
    Awesome blog. It really highlights the fundamentals and its really a quick learning content

  • Anonymous
    June 04, 2014
    Simply fabulous explanation. Exceptionally crisp and clear. Just fantabulous blog.

  • Anonymous
    July 20, 2014
    Best post I found so far on Expressions.

  • Anonymous
    August 18, 2014
    The comment has been removed