zoukankan      html  css  js  c++  java
  • Lambda表达式和表达式树

    一: Lambda表达式

    首先,表达式的类型本身并非委托类型,但它可以通过多种方式隐式或者显式地转换成一个委托实例。匿名函数这个术语同时涵盖了匿名方法和Lambda,很多情况下两者可以使用相互转换原则。

    1.用匿名方法创建委托实例。                     
     Func<string, int> returnlength = delegate(string text) { return text.Length; };
    对照的直接用lambda形式实现上述方法,代码如下:
      Func<string, int> returnlength = (string text) => { return text.Length; };
    等同于
    Func<string, int> returnlength = (string text) => text.Length;
    或者
    Func<string, int> returnlength = (text) => text.Length;
    在阅读lanbda表达式时,可以将 => 部分看成 ”goes to“。

     一: 表达式树

    1.1基本知识

    表达式树提供了一种抽象的方式将一些代码表示成一个对象树,表达式树主要用于LINQ,树中的每个节点本身都是一个表达式。

    不同的表达式类型代表能在代码中执行的不同操作:二元操作,一元操作,方法调用,构造函数调用等等。

    System.Linq.Expressions命名空间包含了代表表达式的各个类,它们都继承自Expression,一个抽象的主要包含一些静态工厂方法的类,这些方法用于创建其他表达式类的实例,然而,Expression类也包括两个属性。

    1.Type属性代表表达式求值后的.NET类型,可把它视为一个返回类型。例如一个表达式要获取一个字符串的Length属性,该表达式的类型就是int。

    2.NodeType属性返回所代表的表达式的种类。它是ExpressionType枚举的成员,包括LessThan、Multiply和Invoke等。仍然使用上面的例子,对于myString.Length这个属性访问来说,其节点类型是MemberAccess。。

    并且该属性能区分由相同的类表示的不同种类的表达式。

    示例如下:

        Expression first = Expression.Constant(2);
        Expression second = Expression.Constant(3);
        Expression add = Expression.Add(first, second);

          Func<int> acmpiled = Expression.Lambda<Func<int>>(add).Compile();   //编译成可执行的委托方法。

        Debug.Write(add);

    该代码会产生输出“(2+3)”,这意味着这些表达式树类覆盖了ToString来产生可读的输出。

    注意:“叶”表达式在代码中是最先创建的,我们需要自上而下构建这些表达式。

    1.2表达式树与委托

    LambdaExpression是从Expression派生的类型之一,泛型类 Expression<TDelegate>又是从LambdaExpression派生的。Expression与 Expression<TDelegate>的区别在于:泛型类以静态类型的方法标识了它是什么种类的表达式,也就是说,他确定了返回类型和参数。所以显然,TDelegate必须是一个委托类型。

    注意:并非所有的Lambda表达式都能转换成表达式树。不能将带有一个语句块(即使只有一个return语句)的Lambda转换成表达式树,只有对单个表达式进行求值的lambda才可以。表达式中不能包含赋值操作,因为在表达式中表示不了这种操作。

    示例二如下:

          Expression<Func<string, string, bool>> expression = (x, y) =>  x.StartsWith(y);
    
          Func<string, string, bool> complied = expression.Compile();
    
          Debug.Write(complied("first", "second"));
          Debug.Write(complied("first", "fir"));

    示例二等同于如下代码:

                //构造调用方法的各个组件
                MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) }); //方法
                ParameterExpression target= Expression.Parameter(typeof(string), "x"); //方法主
                var methodArg = Expression.Parameter(typeof(string), "y"); //参数
                Expression[] methodArgs = new [] { methodArg };  //参数列表
                MethodCallExpression call = Expression.Call(target, method, methodArgs); //从以上组件创建CallExpression
                //将call转换为lambda表达式
                ParameterExpression[] lambdaParameters = new[] { target, methodArg };  //参数
                var lambda = Expression.Lambda<Func<string, string, bool>>(call, lambdaParameters);
                Func<string, string, bool> complied = lambda.Compile();
    
                Debug.Write(complied("first", "second"));
                Debug.Write(complied("first", "fir")); 
  • 相关阅读:
    二级指针也引用
    可视化 linux 无法启动eclipse 报错No java virtual machine
    java报错java/lang/NoClassDefFoundError: java/lang/Object
    hadoop多次搭建后,完整总结(累死宝宝了,搭建了十多遍了)
    hadoop显示ConnectionrRefused
    hadoop搭建初步总结
    VMware 12 的vmware tools安装和如何使用(系统是CENTOS6.5)
    LInux配置jdk(mac和windows)
    LInux javac时, 提示command not found
    myeclipse如何修改Web项目名称,eclipse如何修改项目名字
  • 原文地址:https://www.cnblogs.com/caoheyang911016/p/4272574.html
Copyright © 2011-2022 走看看