看下面2行代码:

  Func<int, int, int> func = (m, n) => m * n + 2; //匿名方法
  Expression<Func<int, int, int>> exp = (m, n) => m * n + 2;//用快捷方式(就是用lambda)声明一个表达式目录树

 第一行是用lambda表达式表明了一个委托,第二行代码则是声明了一个表达式目录树,左边代码虽然看着一样,但是其实是不一样的。使用ExpressionTreeVisualizer工具查看exp会发现这里和上面的委托是完全不一样的,这里面将变量和常量等都做了解析。它类似于一个树形结构,描述不同变量和常量之间的关系,是一种数据结构

c# 表达式目录树_lambda表达式

 

 更具体形象一点可以看下图,将其层层解析出来:

c# 表达式目录树_lambda表达式_02

 

 通过上面我们可以知道一个委托和表达式目录树都可以通过一个lambda表达式来表示,但是却不是一种东西,但是,委托和表达式目录树是可以进行转换的。

                 int iResult1 = func.Invoke(12, 23);
                //exp.Compile()=> 委托; 
                int iResult2 = exp.Compile().Invoke(12, 23); //12 * 23 +2  278

 

看上面代码,通过compile方法可以转换成委托。

还有一点需要注意,用lambda表达式声明表达式目录树的时候不能有语句体(就是{}),只能有一行代码:

     Expression<Func<int, int, int>> exp1 = (m, n) =>
                    {
                        return m * n + 2;
                    };

上面的代码就是错误的,需要改成:

   Expression<Func<int, int, int>> exp1 = (m, n) => m * n + 2;

 

手动拼装表达式目录树

先插一句,如果需要将现有的通过lambda形式声明出来的表达式目录树换成手动拼装的,而且本身对其不怎么熟悉的话可以通过反编译工具查看编译工具中c#语言对应的表达式目录树写法。很有用

示例1 先看一个非常简单的:

Expression<Func<int>> expression = () => 123 + 234; 

 

 现在我们不使用lambda表达式来声明表达式目录树了,我们手动拼装:

                  //手动拼装表达式目录树,不是用的lambda的快捷方式
                {
                    //Expression<Func<int>> expression = () => 123 + 234; 
                    //ConstantExpression表示具有常数值的表达式,
                    ConstantExpression left = Expression.Constant(123, typeof(int));
                    //也可以这样写,第二个参数不必写
                    //ConstantExpression left = Expression.Constant(123);
                    ConstantExpression right = Expression.Constant(234, typeof(int));
                    //Add表示加,如果是乘的话就要用Multiply
                    var plus = Expression.Add(left, right);
                    //完成拼装
                    Expression<Func<int>> expression = Expression.Lambda<Func<int>>(plus, new ParameterExpression[0]);
                    //转换成委托并执行
                    int iResult = expression.Compile().Invoke();
                    int iResult1 = expression.Compile()();
                }

 

示例2 下面看一个稍微复杂一点的:

                    // 更复杂一点的:
                    Expression<Func<int, int, int>> expression = (m, n) => m * n + m + n + 2; 

 

手动拼装:

// 更复杂一点的:
                    //Expression<Func<int, int, int>> expression = (m, n) => m * n + m + n + 2; 
                    //声明变量
                    ParameterExpression m = Expression.Parameter(typeof(int), "m");
                    ParameterExpression n = Expression.Parameter(typeof(int), "n");
                    //常量2
                    ConstantExpression constant2 = Expression.Constant(2, typeof(int));
                    var multiply = Expression.Multiply(m, n);
                    var plus1 = Expression.Add(multiply, m);
                    var plus2 = Expression.Add(plus1, n);
                    var plus = Expression.Add(plus2, constant2);
                    Expression<Func<int, int, int>> expression = Expression.Lambda<Func<int, int, int>>(plus, new ParameterExpression[]
                    {
                        m,
                        n
                    });
                    int iResult = expression.Compile().Invoke(12, 10);

                }

 

 示例3:

   Expression<Func<People, bool>> lambda = (x) => x.Id.ToString().Equals("5"); 

 

 手动拼装: