我需要创建一个动态的linq表达式,我开始使用很多例子。我测试了一些和一些工作而一些没有。在这种情况下,我想创建一个看起来像这样的方法:
public bool Check(int intvar)
{
if ( i > 2 )
return true;
else
return false;
}
现在我写了以下内容:
LabelTarget returnTarget = Expression.Label("label");
ParameterExpression para = Expression.Parameter(typeof(int), "intvalue");
Expression test = Expression.GreaterThan(para, Expression.Constant(5));
Expression iftrue = Expression.Return(returnTarget, Expression.Constant(true));
Expression iffalse = Expression.Return(returnTarget, Expression.Constant(false));
Expression.IfThenElse(test, iftrue, iffalse);
this.TheExpression = Expression.IfThenElse(test, iftrue, iffalse);
Expression.Lambda<Action<int>>(
this.TheExpression,
new ParameterExpression[] { para }
).Compile()(5);
现在抛出InvalidOperationException
:
无法跳转到标签&#34;标签&#34;`
有什么问题?我只需要返回真或假。
答案 0 :(得分:18)
你需要改变一些事情:
如René建议的那样,将函数底部的返回标签放在块表达式中。这是您的return
语句将跳转的地方。
将Lambda声明为Func<int, bool>
类型。由于您需要返回值,因此这需要是一个函数,而不是一个操作。
将returnTarget
标签声明为bool
类型。由于块表达式的返回值是其最后一个语句的值,因此标签必须是正确的类型。
为最终标签提供默认值(=如果通过正常控制流而不是return
语句到达标签,则返回函数的返回值。)
LabelTarget returnTarget = Expression.Label(typeof(bool));
ParameterExpression para = Expression.Parameter(typeof(int), "intvalue");
Expression test = Expression.GreaterThan(para, Expression.Constant(5));
Expression iftrue = Expression.Return(returnTarget, Expression.Constant(true));
Expression iffalse = Expression.Return(returnTarget, Expression.Constant(false));
var ex = Expression.Block(
Expression.IfThenElse(test, iftrue, iffalse),
Expression.Label(returnTarget, Expression.Constant(false)));
var compiled = Expression.Lambda<Func<int, bool>>(
ex,
new ParameterExpression[] { para }
).Compile();
Console.WriteLine(compiled(5)); // prints "False"
Console.WriteLine(compiled(6)); // prints "True"
答案 1 :(得分:1)
returnTarget
目前仅由if / then / else语句引用。标签不会放在任何地方的声明中。所以它不知道去哪里。标签仅定义和引用,但未放置。
尝试使用Expression.Block
合并您的lambda和标签。
Expression.Lambda<Action<int>>(
Expression.Block(
this.TheExpression,
Expression.Label(returnTarget)
),
new ParameterExpression[] { para }
).Compile()(5);
尚未测试过,但这是您找到答案的一般方向。
-update-测试它,上面的lambda编译并运行就好了。
-update2-显然,你想要返回一个值,让我看看,至少,它应该是Func
而不是Action
。
答案 2 :(得分:0)
如果您有这样的简单条件语句:
listOfObjects
您可以将其转换为三元表达式:if (condition)
return expression1;
else
return expression2;
。
然后您可以创建表达式而无需使用condition ? expression1 : expression2
,Label
或Return
。
Goto