【问题标题】:Print the lambda passed to a Func object打印传递给 Func 对象的 lambda
【发布时间】:2021-04-19 15:46:04
【问题描述】:

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

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

如果

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

那么如何生成Expression&lt;Func&lt;double,double&gt;&gt; 以产生相同的结果?表达式构造函数是内部的,Func 类型和它们的表达式之间没有隐式转换。

【问题讨论】:

  • 你不能。当您执行Expression&lt;...&gt; expr = x =&gt; ... 时,C# 编译器会发出在运行时构造该表达式树的代码。当您执行Func&lt;...&gt; f = x =&gt; ... 时,编译器会发出实际上执行您所要求的事情的代码,并丢弃创建表达式所需的所有信息。
  • 我能问一下你为什么要这样做吗?是某种调试支持吗?
  • @Neil :我认为在对微积分模块。更容易区分 NUnit 测试用例(使用 TestCase 属性时,NUnit 只需 .ToString 测试用例名称中的 args)。

标签: c# lambda expression


【解决方案1】:

你不能。

当你写作时:

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 类中的方法从各个部分构建它。如果您使用 lambda,编译器会巧妙地发出在运行时执行此操作的代码。但是,您不能从 已编译 方法开始。

请参阅SharpLab 上的示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多