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

      6.       Lambda Expressions Lambda表达式)与Expressions 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<intint> func = input => input * input;
Expression
<Func<intint>> expression = input => input * input;
Expression
<Func<intbool>> filter = n => (n * 3< 5
    我们必须要使用的类型是System.Linq.Expressions命名空间中的Expression<T>,而这个T是定义表达式签名的委托的类型,这种把一个Lambda表达式看做一个数据结构而嵌套在另一个Lambda表达式中的做法使得现在的expression不是一个委托而是表达式树的数据结构了。接下来的问题是我们应该如何使用这个表达式树呢?请看完整的代码:
            Func<intint> func = input => input * input;
            Console.WriteLine(func(
3).ToString());

            Expression
<Func<intint>> expression = input => input * input;
            Func
<intint> fun = expression.Compile();
            Console.WriteLine(fun(
5).ToString());

            Expression
<Func<intbool>> filter = n => (n * 3< 5;
            BinaryExpression lt 
= (BinaryExpression)filter.Body;
            BinaryExpression mult 
= (BinaryExpression)lt.Left;
            ParameterExpression en 
= (ParameterExpression)mult.Left;
            ConstantExpression three 
= (ConstantExpression)mult.Right;
            ConstantExpression five 
= (ConstantExpression)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是可执行代码而expression是数据,所以在使用方式上也会有所差别的,希望以上这些代码可以很好地让你理解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

posted @ 2008-06-19 16:28  peida  阅读(694)  评论(0编辑  收藏  举报