By Dave Cameron


2009-04-20 10:40:45 8 Comments

Going from a lambda to an Expression is easy using a method call...

public void GimmeExpression(Expression<Func<T>> expression)
{
    ((MemberExpression)expression.Body).Member.Name; // "DoStuff"
}

public void SomewhereElse()
{
    GimmeExpression(() => thing.DoStuff());
}

But I would like to turn the Func in to an expression, only in rare cases...

public void ContainTheDanger(Func<T> dangerousCall)
{
    try 
    {
        dangerousCall();
    }
    catch (Exception e)
    {
        // This next line does not work...
        Expression<Func<T>> DangerousExpression = dangerousCall;
        var nameOfDanger = 
            ((MemberExpression)dangerousCall.Body).Member.Name;
        throw new DangerContainer(
            "Danger manifested while " + nameOfDanger, e);
    }
}

public void SomewhereElse()
{
    ContainTheDanger(() => thing.CrossTheStreams());
}

The line that does not work gives me the compile-time error Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'. An explicit cast does not resolve the situation. Is there a facility to do this that I am overlooking?

9 comments

@Sagi 2012-09-02 17:29:07

NJection.LambdaConverter is a library that converts delegates to expression

public class Program
{
    private static void Main(string[] args) {
       var lambda = Lambda.TransformMethodTo<Func<string, int>>()
                          .From(() => Parse)
                          .ToLambda();            
    }   

    public static int Parse(string value) {
       return int.Parse(value)
    } 
}

@mheyman 2014-02-17 21:22:52

Change

// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;

To

// This next line works!
Expression<Func<T>> DangerousExpression = () => dangerousCall();

@Roman Pokrovskij 2017-11-13 12:40:09

Servy, it as absolutely legal way to get an expression. syntax sugar to build it though expression.lambda and expression.call. Why do you think it should fail at runtime?

@Mehrdad Afshari 2009-04-20 10:43:10

Ooh, it's not easy at all. Func<T> represents a generic delegate and not an expression. If there's any way you could do so (due to optimizations and other things done by the compiler, some data might be thrown away, so it might be impossible to get the original expression back), it'd be disassembling the IL on the fly and inferring the expression (which is by no means easy). Treating lambda expressions as data (Expression<Func<T>>) is a magic done by the compiler (basically the compiler builds an expression tree in code instead of compiling it to IL).

Related fact

This is why languages that push lambdas to the extreme (like Lisp) are often easier to implement as interpreters. In those languages, code and data are essentially the same thing (even at run time), but our chip cannot understand that form of code, so we have to emulate such a machine by building an interpreter on top of it that understands it (the choice made by Lisp like languages) or sacrificing the power (code will no longer be exactly equal to data) to some extent (the choice made by C#). In C#, the compiler gives the illusion of treating code as data by allowing lambdas to be interpreted as code (Func<T>) and data (Expression<Func<T>>) at compile time.

@configurator 2011-05-30 12:02:16

Lisp doesn't have to be interpreted, it can easily be compiled. Macros would have to be expanded at compile time, and if you want to support eval you would need to start up the compiler, but other than that, there's no problem at all doing that.

@mheyman 2014-02-17 21:19:46

"Expression<Func<T>> DangerousExpression = () => dangerousCall();" is not easy?

@Nenad 2014-12-05 20:55:34

@mheyman That would create new Expression about your wrapper action, but it would have no expression tree info about internals of dangerousCall delegate.

@Dmitry Dzygin 2013-03-21 12:38:54

 Expression<Func<T>> ToExpression<T>(Func<T> call)
        {
            MethodCallExpression methodCall = call.Target == null
                ? Expression.Call(call.Method)
                : Expression.Call(Expression.Constant(call.Target), call.Method);

            return Expression.Lambda<Func<T>>(methodCall);
        }

@Holf 2015-10-15 12:01:20

This will not work, as described in other answers.

@Dmitry Dzygin 2015-10-15 14:13:37

Can you elaborate the "this will not work" part? Have you actually tried compiling and executing it? Or it doesn't work particularly in your application?

@Eli Gassert 2016-11-23 08:42:34

FWIW, this might not be what the main ticket was about, but it was what I needed. It was the call.Target part that was killing me. It worked for years, and then suddenly stopped working and started complaining about a static/non-static blah blah. Anyway, thanks!

@Override 2011-02-27 13:48:59

    private static Expression<Func<T, bool>> FuncToExpression<T>(Func<T, bool> f)  
    {  
        return x => f(x);  
    } 

@Dave Cameron 2011-03-15 13:58:27

I wanted to traverse the syntax tree of the returned expression. Would this approach allow me to do that?

@Jonno 2012-03-01 13:43:24

@DaveCameron - No. See above answers - the already compiled Func will be hidden in a new Expression. This simply adds one layer of data over code; you could traverse one layer just to find your parameter f without further details, so you're right where you started.

@nawfal 2013-06-01 05:51:00

Jono is right, this doesnt help OP..

@Holf 2015-10-15 12:01:01

This will not work, as described in other answers.

@aaguiar 2009-05-01 19:38:41

JB Evain from the Cecil Mono team is doing some progress to enable this

http://evain.net/blog/articles/2009/04/22/converting-delegates-to-expression-trees

@Steve Willcock 2009-04-20 10:55:39

You can go the other way via the .Compile() method however - not sure if this is useful for you:

public void ContainTheDanger<T>(Expression<Func<T>> dangerousCall)
{
    try
    {
        var expr = dangerousCall.Compile();
        expr.Invoke();
    }
    catch (Exception e)
    {
        Expression<Func<T>> DangerousExpression = dangerousCall;
        var nameOfDanger = ((MethodCallExpression)dangerousCall.Body).Method.Name;
        throw new DangerContainer("Danger manifested while " + nameOfDanger, e);
    }
}

public void SomewhereElse()
{
    var thing = new Thing();
    ContainTheDanger(() => thing.CrossTheStreams());
}

@David Wengier 2009-04-20 10:53:59

What you probably should do, is turn the method around. Take in an Expression>, and compile and run. If it fails, you already have the Expression to look into.

public void ContainTheDanger(Expression<Func<T>> dangerousCall)
{
    try 
    {
        dangerousCall().Compile().Invoke();;
    }
    catch (Exception e)
    {
        // This next line does not work...
        var nameOfDanger = 
            ((MemberExpression)dangerousCall.Body).Member.Name;
        throw new DangerContainer(
            "Danger manifested while " + nameOfDanger, e);
    }
}

public void SomewhereElse()
{
    ContainTheDanger(() => thing.CrossTheStreams());
}

Obviously you need to consider the performance implications of this, and determine if it is something that you really need to do.

@Marc Gravell 2009-04-20 10:52:58

If you sometimes need an expression and sometimes need a delegate, you have 2 options:

  • have different methods (1 for each)
  • always accept the Expression<...> version, and just .Compile().Invoke(...) it if you want a delegate. Obviously this has cost.

Related Questions

Sponsored Content

10 Answered Questions

[SOLVED] What is a lambda expression in C++11?

10 Answered Questions

[SOLVED] How to escape braces (curly brackets) in a format string in .NET

26 Answered Questions

[SOLVED] How can I get the application's path in a .NET console application?

6 Answered Questions

[SOLVED] Combining two expressions (Expression<Func<T, bool>>)

23 Answered Questions

[SOLVED] Sending email in .NET through Gmail

9 Answered Questions

[SOLVED] Why would you use Expression<Func<T>> rather than Func<T>?

16 Answered Questions

[SOLVED] Difference between decimal, float and double in .NET?

21 Answered Questions

[SOLVED] .NET String.Format() to add commas in thousands place for a number

  • 2008-09-19 21:26:21
  • Seibar
  • 667501 View
  • 790 Score
  • 21 Answer
  • Tags:   c# .net

7 Answered Questions

[SOLVED] Func delegate with no return type

  • 2009-05-27 19:21:42
  • Marcel Lamothe
  • 186140 View
  • 521 Score
  • 7 Answer
  • Tags:   c# .net

Sponsored Content