2016-12-21 128 views
4

我第一次探索表达式树。我有一些基本的疑问。C表达式树#

所以基本上,表达式只需要一个lambda表达式。然后,我们可以将lambda表达式编译()为MSIL代码,MSIL代码又返回一个通用委托。我们可以照原样调用返回的委托。我的理解是否正确?

如果它是在这里就是我想实现:((10*5)+(9/4))

BinaryExpression b1 = Expression.MakeBinary(ExpressionType.Multiply, Expression.Constant(10), Expression.Constant(5));//(10*5) 
BinaryExpression b2 = Expression.MakeBinary(ExpressionType.Divide, Expression.Constant(9), Expression.Constant(4));//(9/4) 
BinaryExpression b4 = Expression.MakeBinary(ExpressionType.Add, b1, b2);//((10*5)+(9/4)) 

所以在这一点上,我们已经取得了lambda expression body。现在把它变成一个full lambda expression我们需要调用

Console.WriteLine(Expression.Lambda<Func<int, int>>(b4).Compile()); 

我没有得到这部分。这也不起作用。

为什么这Func<int,int>

它是否像内部表达式将只需要int作为参数,整个表达式将返回一个int?

显然这是行不通的。生成的lambda如何看起来像?

我得到整个图片?如何使这项工作?

+1

*这不也行*,它有什么作用?它会给你一个错误?什么错误? –

回答

6
Expression.Lambda<Func<int, int>>(b4).Compile() 

Func<int,int>是为采取单一int参数,并返回一个int lambda表达式的签名。你的lambda具有不同的签名。

显然这是行不通的。

您的lambda不带任何参数,因此您需要Func<int>来代替。

生成的lambda如何看起来像?

生成的lambda是一个可调用的对象。如果您想以评估你回来的表达,演员和调用它,就像这样:

var compiledLambda = (Func<int>)Expression.Lambda<Func<int>>(b4).Compile(); 
Console.WriteLine(compiledLambda()); 
//        ^^ 

上面打印52,符合市场预期。

Demo 1.

如果你想作一个Func<int,int>,参数添加到您的表达,例如使其(p*5)+(9/4)其中pint参数:

ParameterExpression p = Expression.Parameter(typeof(int)); 
BinaryExpression b1 = Expression.MakeBinary(ExpressionType.Multiply, p, Expression.Constant(5));//(p*5) 
BinaryExpression b2 = Expression.MakeBinary(ExpressionType.Divide, Expression.Constant(9), Expression.Constant(4));//(9/4) 
BinaryExpression b4 = Expression.MakeBinary(ExpressionType.Add, b1, b2); 
var compiledLambda = (Func<int,int>)Expression.Lambda<Func<int,int>>(b4, new[] {p}).Compile(); 
Console.WriteLine(compiledLambda(10)); // Prints 52 
Console.WriteLine(compiledLambda(8)); // Prints 42 

Demo 2.

1

使用:

Console.WriteLine(Expression.Lambda<Func<int, int>>(b4).Compile()); 

你实际上Console.WriteLine(object)超载它打印参数的Type的名字打印出来。

,因为该行:

Expression.Lambda<Func<int>>(b4).Compile(); 

只编译Lambda和为您提供的delegate - 不是它调用的结果

您需要调用编译拉姆达并打印结果:

Func<int> result = (Func<int>)Expression.Lambda<Func<int>>(b4).Compile(); 
Console.WriteLine(result()); 

另外请注意,你试图编译delegateFunc<int,int>这需要一个int参数和提供了一个int结果,但您的代码不需要参数,因此您需要使用Func<int>

4

您可以创建lambda表达式这样的:

LambdaExpression lb = Expression.Lambda(b4); 

然后,您可以编译这个表达式的委托:

Delegate dlg = lb.Compile(); 

而且施放此委托给一个Func<int>

Func<int> f = (Func<int>)dlg; 

你可以像往常一样使用它:

Console.WriteLine(f()); // 52 

通用的方式工作了。为什么您使用Func<int,int>?你表达不带输入,并返回一个int

Func<int> f = Expression.Lambda<Func<int>>(b4); 

通用参数导致LambdaExpressionCompile方法返回一个Func<int>而不是Delegate,你就需要再投的。