linq学习笔记(1):c#3.0新特性(3)

长平狐 发布于 2013/06/17 12:55
阅读 55
收藏 0
       6.       Lambda Exssions Lambda表达式)与Exssions Tree(表达式树)
    什么是Lambda表达式?我们可以认为它是匿名方法的简洁写法,例如下面这个匿名方法:
            delegate ( int  age) 
            { 
                
return  age  <   18
            }
    我们就可以写成 Lambda 表达式的形式:
age  =>  age  <   18 ;
    Lambda 表达式, 例如:
 var list  =   new [] {  " aa " " bb " " ac "  };
            var result 
=  Array.FindAll(list, s  =>  (s.IndexOf( " a " >   - 1 ));
            
foreach  (var v  in  result)
                Console.WriteLine(v);
      Lambda 表达式格式:( 参数列表)=> 表达式或语句块
    具体意义:定义Lambda 接受参数列表,运行表达式或语句块返回表达式或语句块的值传给这个参数列表。
    
=> Lambda 表达式的标识符而不是运算符,显而易见,=> 的作用就是{} 花括号的作用.
      Lambda 表达式参数类型可以是隐式类型或显式类型。在显式列表中,每个参数的类型是显式指定的,在隐式列表中,参数的类型由Lambda 表达式出现的语境自动推断类型。
    
Lambda 表达式的参数列表可以有一个或多个参数,或者无参数。在有单一的隐型参数的lambda 表达式中,圆括号可以从参数列表中省略,但是多个参数或者没有参数以及需要显式地为参数设置数据类型的情况下,圆括号就不能省略了。例如:
(x, y)  =>  x  *  y; // 多参数,隐式类型=>表达式
=>  x  *   10 ; // 单参数,隐式类型=>表达式
=>  {  return  x  *   10 ; };  // 单参数,隐式类型=>语句块
( int  x)  =>  x  *   10 ; // 单参数,显式类型=>表达式
( int  x)  =>  {  return  x  *   10 ; }; // 单参数,显式类型=>语句块
()  =>  Console.WriteLine();  // 无参数
    在前面的帖子中,我们写了一个Person类及增加了2个人,接下来,我们使用由LINQ提供的新的WhereAverage方法来返回集合中的人的一个子集,以及计算这个集合中的人的平均年龄:
            IList < Person >  PersonList  =   new  List < Person >  
            { 
                
new  Person { UserID  =   1 , UserAge  =   29 , UserName  =   " peida "  }, 
                
new  Person { UserID  =   2 , UserAge  =   35 , UserName  =   " bamboo "  }
            };

            
// 获取特定人时所用的过滤条件,p参数属于Person类型
            var results  =  PersonList.Where(p  =>  p.UserName  ==   " peida " ).ToList();
            
// 用Person对象的UserAge值计算平均年龄
            var average  =  PersonList.Average(p  =>  p.UserAge);
    上面的相当于下面的:
            var resultsPersondelegate  =  PersonList.Where( delegate (Person p)
            {
                
return  p.UserName  ==   " peida " ; //  返回一个布尔值
            });
            var averagePersonAgedelegate 
=  PersonList.Average( delegate (Person p)
            {
                
return  p.UserAge;
            });
      Lambda 表达式可以被转换为委托类型,需要满足以下条件: Lambda 表达式的参数类型要与委托类型的参数个数相等,类型相同,返回类型相同,无论是表达式,还是语句块。注意隐式类型要参与类型辨析。
    
Lambda 表达式树
    
Lambda 表达式树允许我们像处理数据(比如读取,修改)一样来处理 Lambda 表达式,表达式树典型的声明形式是:
Func < int int >  func  =  input  =>  input  *  input;
Exssion
< Func < int int >>  exssion  =  input  =>  input  *  input;
Exssion
< Func < int bool >>  filter  =  n  =>  (n  *   3 <   5
    我们必须要使用的类型是 System.Linq.Exssions 命名空间中的 Exssion<T> ,而这个 T 是定义表达式签名的委托的类型,这种把一个 Lambda 表达式看做一个数据结构而嵌套在另一个 Lambda 表达式中的做法使得现在的 exssion 不是一个委托而是表达式树的数据结构了。接下来的问题是我们应该如何使用这个表达式树呢?请看完整的代码:
            Func < int int >  func  =  input  =>  input  *  input;
            Console.WriteLine(func(
3 ).ToString());

            Exssion
< Func < int int >>  exssion  =  input  =>  input  *  input;
            Func
< int int >  fun  =  exssion.Compile();
            Console.WriteLine(fun(
5 ).ToString());

            Exssion
< Func < int bool >>  filter  =  n  =>  (n  *   3 <   5 ;
            BinaryExssion lt 
=  (BinaryExssion)filter.Body;
            BinaryExssion mult 
=  (BinaryExssion)lt.Left;
            ParameterExssion en 
=  (ParameterExssion)mult.Left;
            ConstantExssion three 
=  (ConstantExssion)mult.Right;
            ConstantExssion five 
=  (ConstantExssion)lt.Right;
            var One 
=  filter.Compile();
            Console.WriteLine(
" Result: {0},{1} " , One( 5 ), One( 1 ));
            Console.WriteLine(
" ({0} ({1} {2} {3}) {4}) " , lt.NodeType,
                     mult.NodeType, en.Name, three.Value, five.Value);
    因为 func 是可执行代码而 exssion 是数据,所以在使用方式上也会有所差别的,希望以上这些代码可以很好地让你理解 Lambda 表达式以及表达式树这两个概念。
    
Lambda 表达式和Lambda 表达式树要点:
      Lambda 表达式的参数类型可以忽略,因为可以根据使用的上下文进行推断。  
      Lambda 表达式的主体 (body) 可以是表达式,也可以是语句块。  
      Lambda 表达式传入的实参将参与类型推断,以及方法重载辨析。  
      Lambda 表达式和表达式体可以被转换为表达式树。
    
表达式树允许 lambda 表达式能够代表数据结构替代表示为执行代码。
    【参考资料】
      http://www.cnblogs.com/Autumoon/category/112473.html
    http://www.cnblogs.com/lyj/archive/2008/03/25/1119671.html


原文链接:http://www.cnblogs.com/peida/archive/2008/06/19/1226017.html
加载中
返回顶部
顶部