Wednesday, November 22, 2006 2:20 PM bart

Getting started with C# 3.0 Expression Trees

Somewhere in October this year, a series of three posts appeared online on this blog, covering "DynCalc", focusing on dynamic compilation:

Strictly spoken, this post is part of this series. The first three parts of this posting series were meant to provide the introduction to expression trees in C# 3.0. In this post, I'll introduce C# 3.0 Expression Trees very briefly. A future post will connect the DynCalc idea to C# 3.0 Expression Trees further on.

C# 3.0 focuses on one big innovation: LINQ (Language INtegrated Query), which has been discussed previously on this blog as well. The basic idea is to close the gap between all sorts of data representations, including objects, relational data and hierarchical data (XML). In order to provide developers an integrated query syntax in the language itself (which leads to type safety, catching errors at compile time, etc instead of the opaque SQL statements inside some string), the language has been extended with (context-sensitive, in order to maintain backward compatibility) keywords like from, where, orderby, etc. A typical example is shown below:

var res = from p in System.Diagnostics.Process.GetProcesses() where p.HandleCount > 100 select new { Name = p.ProcessName, p.WorkingSet }; foreach (var i in res) { Console.WriteLine("{0,-30}{1}", p.Name, p.WorkingSet); }

The first line contains quite some C# 3.0 features:

  • Local type inference with the var keyword, which is in this case a requirement since we construct an anonymous type (see third bullet).
  • LINQ syntax to formulate a query selecting objects (LINQ-to-Objects).
  • Anymous type creation using the new { ... } syntax.

For this discussion, it's important to see that the first line - the LINQ query - is compiled to IL code directly. Basically, the compiler rewrites the line as:

var res = System.Diagnostics.Process.GetProcesses().Where(p => p.HandleCount > 100).Select(p => new { Name = p.ProcessName, p.WorkingSet});

In here, extension methods are used on IEnumerable<T>, provided by the System.Query namespace's Sequence class. In reality this code is equivalent to:

var res1 = System.Query.Sequence.Where(System.Diagnostics.Process.GetProcesses(), p => p.HandleCount > 100); var res = System.Query.Sequence.Select(res1, p => new { Name = p.ProcessName, p.WorkingSet });

Which, on its turn is translated to get rid of the lamba expressions (which become anonymous methods) and the anymous type syntax (which becomes a constructor call to some auto-generated private class, together with two property setter calls). However, if one wants to run a query against a relational source, we don't want such an extensive compilation to IL. Instead we want some kind of tree that represents the query but can be translated (at runtime) into some domain-specific querying language like SQL or XQuery or LDAP or WQL or ..., you get the idea (strictly spoken I should mention IQueryable<T> here, but I'll defer that discussion to a future post). This is where expression trees enter the picture.

In the code fragment below, you can see a first example on how expression trees are created for lambda expressions. Instead of just doing something like Func<int> f = () => 2 * 3 + 1; (which results in a compiled method which can be called like int res = f();) one can wrap the declaration in an Expression<T> object. This makes the C# compiler generate an expression tree instead of performing direct compilation. Next, you could parse the tree yourself manually, or request compilation at runtime by calling Compile(). Below, you can see how the expression tree for 2 * 3 + 1 can be created directly or manually (which we'll do later when combining this with our DynCalc "front-end").

using System; using System.Collections.Generic; using System.Text; using System.Query; using System.Expressions; namespace ModernDynCalc { class Program { static void Main(string[] args) { Expression<Func<int>> f = () => 2 * 3 + 1; int res = f.Compile().Invoke(); Console.WriteLine(res); Expression<Func<int>> f2 = Expression<Func<int>>.Lambda<Func<int>>( Expression.Add( Expression.Multiply( Expression.Constant(2), Expression.Constant(3) ), Expression.Constant(1) ), new ParameterExpression[0] ); int res2 = f2.Compile().Invoke(); Console.WriteLine(res2); } } }

In a next post, we'll combine this with our DynCalc effort, and yet later, a more extensive sample will be shown on how to use a "LINQ expression tree" to translate a query into some target query statement. Enjoy!

kick it on DotNetKicks.com

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under:

Comments

# links for 2006-11-23

Thursday, November 23, 2006 11:22 PM by Impersonation Failure

Automatic Properties - The Video New languages extension proposed for inclusing in C# 3.0. Automatic

# links for 2006-11-24

Friday, November 24, 2006 2:21 AM by Impersonation Failure

Symbian Developer Network - Developer Tools In addition to what is shipped on Symbian OS SDKs, there

# The IQueryable tales - LINQ to LDAP - Part 0

Thursday, April 05, 2007 7:04 PM by B# .NET Blog

Here we are again for some cool LINQ stuff. In the past I've been blogging on C# 3.0 language innovation

# The IQueryable tales - LINQ to LDAP - Part 0: Introduction

Friday, April 06, 2007 5:04 AM by B# .NET Blog

Here we are again for some cool LINQ stuff. In the past I've been blogging on C# 3.0 language innovation

# The Evolution of Lambda Functions in C#

Thursday, March 20, 2008 7:58 AM by Rick's Development Wonderland

Howard Dierking over at MSDN has a really interesting Blog post entitled " Lambda, Lambda, Lambda! "

# Haytham El-Fadeel &raquo; Blog Archive &raquo; The Evolution of Lambda Functions in C#

Pingback from  Haytham El-Fadeel  &raquo; Blog Archive   &raquo; The Evolution of Lambda Functions in C#

# Haytham El-Fadeel &raquo; Blog Archive &raquo; The Evolution of Lambda Functions in C#

Pingback from  Haytham El-Fadeel  &raquo; Blog Archive   &raquo; The Evolution of Lambda Functions in C#