【问题标题】:Expressions... What am I doing wrong?表达式...我做错了什么?
【发布时间】:2012-09-05 12:26:56
【问题描述】:

我决定花一些黄金时间来学习更多关于表达式的知识。我正在尝试一个非常简单的练习,即添加两个数字。我遇到了一个很难搜索的异常。

这是我的代码

Expression<Func<int,int,int>> addExpr = (x, y) => x + y;
var p1 = Expression.Parameter(typeof(int), "p1");
var p2 = Expression.Parameter(typeof(int), "p2");
var lambda = Expression.Lambda<Func<int,int,int>>(addExpr, p1, p2); //<-here
var del = lambda.Compile();
var result = del(2,3); //expect 5

但这会引发 ArgumentException:'System.Func`3[System.Int32,System.Int32,System.Int32]' 类型的表达式不能用于返回类型 'System.Int32'

在上面指出的那一行。我做错了什么?

【问题讨论】:

  • 你想在这段代码中做什么?您是否尝试仅使用表达式构建 (x,y) => x + y lambda?
  • 只是随便看看。最终目标是编写一个倒计时数字游戏求解器的练习。 en.wikipedia.org/wiki/Countdown_%28game_show%29#Numbers_round 在我看来,表达式树是解决这个问题的好方法,但对我来说,这一切都是非常新的和闪亮的 ATM。

标签: c# expression argumentexception


【解决方案1】:

您需要使用表达式参数将addExpr 包装在调用中

Expression<Func<int,int,int>> addExpr = (x, y) => x + y;
var p1 = Expression.Parameter(typeof(int), "p1");
var p2 = Expression.Parameter(typeof(int), "p2");
var invokeExpression=Expression.Invoke(addExpr,p1,p2);
var lambda = Expression.Lambda<Func<int,int,int>>(invokeExpression,p1,p2);
var del = lambda.Compile();
var result=del(2,3);

调用是您如何将 p1 键入 x 并将 p2 键入 y,或者您可以将上面的内容写为

var p1 = Expression.Parameter(typeof(int), "p1");
var p2 = Expression.Parameter(typeof(int), "p2");
var lambda=Expresion.Lambda<Func<int,int,int>>(Expression.Add(p1,p2),p1,p2);
var del = lambda.Compile();
var result=del(2,3);

否则你需要将表达式主体抓取到 lambda 中并传递表达式参数。

var lambda=Expresion.Lambda<Func<int,int,int>>(addExpr.Body,addExpr.Parameters);

【讨论】:

  • 明白了。现在一切就绪。
  • @Spender 毕竟我已经添加了最终更新作为第三个选项。如果您不需要使用其他地方的表达式参数,则此选项将起作用。
  • 感谢您花时间介绍一些替代方案。
【解决方案2】:

你的代码应该是:

var lambda = Expression.Lambda<Func<Expression<Func<int, int, int>>, int, int>(addExpr, p1, p2);

您当前的代码需要int,而您需要传入Expression&lt;Func&lt;int, int, int&gt;&gt;

更新

实际上上面不会编译,你需要这样做:

var lambda = Expression.Lambda<Func<int, int, int>>(Expression.Add(p1, p2), p1, p2);

【讨论】:

  • 是的,这是行不通的,除非你编译并调用传递的表达式。
  • @leppie 是的,我刚刚在那里测试了代码,我已经更新了我的答案以改用Expression.Add
【解决方案3】:

您需要分解addExpr 的主体,或者最好从头开始编写它,即Expression.Add(p1,p2) 而不是addExpr

【讨论】:

  • “分解”是什么意思?假装我有代表 0!
  • @spender: decompose == 拆开即addExpr.Body
  • 谢谢。我马上就到了。
猜你喜欢
  • 2010-12-17
  • 1970-01-01
  • 2022-07-27
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 2021-09-20
  • 1970-01-01
相关资源
最近更新 更多