打印传递给 Func 对象的 lambda

Print the lambda passed to a Func object

我可以像这样打印 lambda 表达式

Expression<Func<double,double>> expr = x => x * x; 
string s = expr.ToString(); // "x => (x * x)" 

但是如果

Func<double, double> function = x => x * x;

那么我怎样才能生成 Expression<Func<double,double>> 来产生相同的结果呢? Expression 构造函数是内部的,Func 类型和它们的 Expression 之间没有隐式转换。

你不能。

当你写:

Expression<Action<int>> e = x => Console.WriteLine(x);

编译器发出(简化):

ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "x");
MethodInfo method = typeof(Console).GetMethod("WriteLine", new[] { typeof(object) });
MethodCallExpression body = Expression.Call(null, method, parameterExpression);
Expression<Action<int>> e = Expression.Lambda<Action<int>>(body, parameterExpression);

看看它实际上是如何发出在运行时重新创建表达式树的代码的?

相比之下,当你写:

Action<int> a = x => Console.WriteLine(x);

编译器发出(简化)

internal void GeneratedMethod(int x)
{
    Console.WriteLine(x);
}

...

Action<int> a = new Action<int>(GeneratedMethod);

看出区别了吗?运行时根本无法采用已编译的方法并为其创建表达式树。

构造表达式树的唯一方法是使用 Expression class 上的方法从各个部分构建它。如果您使用 lambda,编译器会巧妙地发出在运行时执行此操作的代码。但是,您不能从 compiled 方法开始。

参见 SharpLab 上的示例。