tags:

views:

121

answers:

4

I was reading about Expression Tree feature and how you can create delegates using lambda expressions. I still can't get as to in what scenario it is useful and in what real world example should I use it.

+12  A: 

The primary use for expression trees is for out-of-process LINQ providers such as LINQ to SQL.

When you write something like this:

var query = people.Where(x => x.Age > 18)
                  .Select(x => x.Name);

those lambda expressions can either be converted to delegates, which can then be executed (as they are in LINQ to Object) or they can be converted to expression trees, which can be analyzed by the query source and acted on accordingly (e.g. by turning them into SQL, web service calls etc). The difference is that expression trees represent the code as data. They can be compiled into delegates if necessary, but usually (within LINQ anyway) they're never executed directly - just examined to find out the logic they contain.

Expression trees are also used extensively in the Dynamic Language Runtime, where they represent the code which should execute when a dynamic expression is evaluated. Expression trees are well suited for this as they can be composed and broken down again, and after they're compiled the resulting IL is JIT-compiled as normal.

Most developers will never need to mess with the expression tree API, although it has a few other uses.

Jon Skeet
Thanks Jon. I would love to get a live example about where I can use it. I got the concept a bit but unless I can't think of a scenario where using Expression Tree is better than the conventional way of doing, I won't feel comfortable in my mind.
Nimesh
@Nimesh: It *can* be occasionally useful in creating refactor-proof programs which need to use reflection. By specifying a property via lambda expression converted into a delegate instead of a name (as a string), you can extra the string at execution time and know it's correct. But this is really an edge case - it's primarily for LINQ and the DLR (editing to reflect the latter).
Jon Skeet
+1  A: 

I once wrote a class that wraps an XML and an object and used ExpressionTrees to manipulate the XML.

The use would look like this (very basic example):

Class Car
    Public Property Name as String
    Public Property Color as Color
End Class

Dim w = new Wrapper(Of Car)
w.Write(Function(car) car.Name, 'My Car')
w.Write(Function(car) car.Color, Color.Black)

and give you this a XML like this:

<Car>
    <Name>My Car</Name>
    <Color>#000000</Color>
</Car>

It's used in an application to manipulate serialized objects for use with WCF.

The wrapper would look like this (simplified):

Public Sub Write(ByVal exp As Expression(Of Func(Of TObject, String)), ByVal value As String)
    ' Get Propertyname 
    Dim name = DirectCast(exp.Body, MemberExpression).Member.Name '
    ...
    ManipulateXml(name, value)
    ...
End Sub

Public Sub Write(ByVal exp As Expression(Of Func(Of TObject, Color)), ByVal value As Color)
    ' Do something special with Color-Properties, like converting into another format
    ...
    ManipulateXml(name, manipulatedValue)
    ...
End Sub
dkson
Could you please paste all the code (wrapper) with small snippets so to clear my brain. May be it's the effect of Friday afternoon....
Nimesh
@Nimesh: "Wrapper" just extracts the property name from the expression tree.
adrianm
@adrianm Yes, that's basically right, but the wrapper also handles different types differently. for example Strings are copied 1:1 into the XML, colors and dates get convertet into a special format etc. But there's really no magic in here
dkson
+3  A: 

Aside from LINQ, another very simple use case is to extract both the name and the value of a property. I use this in a fluent API for validating data transfer objects. It's safer to pass one lambda parameter to define both name and value rather than have a second string parameter for the name, and run the risk of developers getting it wrong.

Here's an example (minus all the safety checks and other housekeeping):

public Validator<T> Check<T>(Expression<Func<T>> expr) {
    // Analyse the expression as data
    string name = ((MemberExpression) expr.Body).Member.Name;
    // Compile and execute it to get the value
    T value = (expr.Compile())();
    return new Validator<T>(name, value);
}

Example of use:

Check(() => x.Name).NotNull.MinLength(1);
Check(() => x.Age).GreaterThan(18);
Christian Hayter
Very nice validation API, although the performance is probably not that good because of the expression compilation
Thomas Levesque
Yes, there will be a performance overhead. On balance, I thought that the gain in reliability was worth it. Also, the compilation is done only once for each property, and after that you can hammer the constructed validator object as much as you like.
Christian Hayter
+3  A: 

I used expression trees to make a null-safe evaluator:

string name = myObject.NullSafeEval(x => x.Foo.GetBar(42).Baz.Name, "Default");

This methods analyzes and rewrites the expression tree to insert null checks before each property or method call along the "path" to Name. If a null is encountered along the way, the default value is returned.

See implementation here

Expression trees are also commonly used to avoid referring to a property by hard-coding its name in a string:

private string _foo;
public string Foo
{
    get { return _foo; }
    set
    {
        _foo = value;
        OnPropertyChanged(() => Foo);
        // Rather than:
        // OnPropertyChanged("Foo");
    }
}

static string GetPropertyName<T>(Expression<Func<T>> expr)
{
    var memberExpr = expr.Body as MemberExpression;
    if (memberExpr == null)
        throw new ArgumentException("expr", "The expression body must be a member expression");
    return memberExpr.Member.Name;
}

protected void OnPropertyChanged<T>(Expression<Func<T>> expr)
{
    OnPropertyChanged(GetPropertyName(expr));
}

This enables compile time checking and name refactoring

Thomas Levesque
Cool. If only some sort of syntactic equivalent was built into the language... <sigh/>
Christian Hayter
@Christian Hayter: Could you show an example?
Douglas
@Douglas: An example of what?
Christian Hayter
@Christian Hayter: Sorry, I miss-read your comment, I thought you were being sarcastic. As if you thought that there was a simpler way to do what was done in the answer above.
Douglas
@Thomas Levesque: I’m very interested in your `NullSafeEval` method — any chance you could [paste the source for that method](http://csharp.pastebin.com/) and show us? That would be great! ☺
Timwi
@Timwi, the code is available on my blog, there is already a link in my answer ;)
Thomas Levesque
@Thomas Levesque: Ah yeah, thanks! I looked at it, and as I suspected, you manipulate the expression tree and then compile it. I suppose in most cases where utter performance is not that important, it’ll work, but aren’t you worried that you might inadvertantly use it in a tight loop and unwittingly incur a significant performance penalty?
Timwi
Yes, I know it's pretty slow, and I mention it in my post. That's merely a proof of concept, I would definitely not use it in production code (at least not in its current state)
Thomas Levesque