zoukankan      html  css  js  c++  java
  • C# Lambda表达式

    今天高手讨论了一个问题:
    FuncList.FindAll(pNodes => pNodes.ParentID == "01")
    等价于 if(pNodes.ParentID == "01") return pNodes; 
    实际就是一个委托函数的缩写。
    总结一下:
    “Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。 所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。Lambda 表达式 x => x * x 读作“x goes to x times x”。
    http://baike.baidu.com/view/3048187.htm

    Windbey中为了增强对集合的访问能力, MS设计了List<T>这么一个泛型集合, 其中有不少的增强功能,比如Foreach,ConvertAll,FindAll等等,并且为了方便使用MS在System名空间下引入了一些特制的Delegate.主要包括以下几个:

       20     public delegate void Action<T>(T obj);   //Used by ForEach

       21     public delegate int Comparison<T>(T x, T y);  //Used by Sort

       22     public delegate TOutput Converter<TInput, TOutput>(TInput input);    //Used by ConvertAll

       23     public delegate bool Predicate<T>(T obj); //Used by FindAll


    利用这些特制的Delegate,再加上匿名方法的使用,我们可以获得更加简洁,有效的代码. 具体的例子我以前有过介绍.现在在Orcas中, MS加入了lambda表达式的概念. lambda表达式是匿名方法的进一步增强. 利用它可以更加方便的写出新的方法. 而且语义上更加接近人性化.

    同样它也引入了一些特制的Delegate:

       20       public delegate T Func<T>();

       21       public delegate T Func<A0, T>(A0 arg0);

       22       public delegate T Func<A0, A1, T>(A0 arg0, A1 arg1);

       23       public delegate T Func<A0, A1, A2, T>(A0 arg0, A1 arg1, A2 arg2);

       24       public delegate T Func<A0, A1, A2, A3, T>(A0 arg0, A1 arg1, A2 arg2, A3 arg3);


    和2.0中特制的Delegate对比, 你会发现它们有很多相同之处:

       20       public delegate int Comparison<T>(T x, T y);   
       21       public delegate int Func<T,T,int>(T arg0, T arg1);

       22       public delegate TOutput Converter<TInput, TOutput>(TInput input); 
       23       public delegate TOutput Func<TInput, TOutput>(TInput arg0);

       24       public delegate bool Predicate<T>(T obj);

       25       public delegate bool Func<T,bool>(T arg0);


    也就是说3.0中特制的Delegate比2.0的更一般化, 2.0是3.0的特例. 所以我们完全可以将lambda表达式运用于List<T>的一些增强方法中.

    Sort方法

       20  List<int> list=new List<int>();

       21  var numbers = new []{ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

       22  list.AddRange(numbers);

       23  list.Sort(delegate (int a, int b)

       24                {

       25                 return a.CompareTo(b);

       26                }

       27            );

       28  //use lambda

       29  list.Sort((a,b)=>a.CompareTo(b));


    ConvertAll方法

       20  List<int> doubleList =list.ConvertAll<int>(delegate (int i)

       21                                             {

       22                                                 return i*2;

       23                                             });

       24  //use lambda

       25  var doubleList2=list.ConvertAll<int>(i=>i*2);


    FindAll方法


       20  List<int> lowerThanFiveList =list.FindAll(delegate (int i)

       21                                             {

       22                                                 return i<5;

       23                                             }

       24                                           );

       25  var lowerThanFiveList2=list.FindAll(i=>i<5);


    从上面的例子可以看出利用lambda表达式写出的代码更加简洁易懂.  (以后代码都经过编译测试,可不是我杜撰的.)

    以上是将lambda表达式运用于2.0当中. 但是在熟悉了3.0后, 你会发现2.0中的List<T>提供的增强方法完全是多余的了. 其实这些增强方法往往并不限于List<T>, 通常对于IEnumerable<T>对象都是适用的. 但是如果去改动IEnumable<T>接口那么影响实在太大了,将涉及很多的类. 所以MS仅仅在List<T>中提供了这些增强方法. 不过通过List<T>的一个构造函数,你可以使得所有的IEnumerable<T>对象可以方便的转化为List<T>,然后再利用这些方法.

    这可以说是一个很取巧的方法, 不过在有了3.0的Extension Method的支持下, 就不用这么麻烦了, 而且MS还内置了一系列更强的集合操作方法.

    比如之前的FindAll方法,我们现在可以这样写:

       21      var numbers = new []{ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

       22      var lowerThanFive=numbers.Where(i=>i<5); //never need List<T>, just operate on T[] or any other types implement IEnumerable<T>

       23      foreach (var v in lowerThanFive)

       24          Console.WriteLine(v);   


    ConvertAll方法

       21      var doubleList3=numbers.Select(i=>i*2);

       22      foreach (var v in doubleList3)

       23          Console.WriteLine(v); 


    Sort方法

       21      var orderList =numbers.OrderBy(i=>i);

       22      foreach (var v in orderList)

       23          Console.WriteLine(v); 

    甚至还有很多更强大的功能:
    比如我要取numbers数组中最大的5个数.

       21      var big5 =numbers.OrderByDescending(i=>i).Take(5);

       22      foreach (var v in big5)

       23          Console.WriteLine(v);


    通过Orcas的Extension Method和Lambda表达式, MS为集合的操作提供了更加方便强大的功能. 这里尚未用到Standard Query Operators, 不然代码还要被简化. 

    当然Linq现在仅仅是一个Tech Preview 版本. 尚有很多不足.尤其在智能感知(IntelliSense)方面:
    1.  var numbers = new []{ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; 采用这种写法时, numbers没有智能感知功能.
    2. 使用lambda表达式时,如果不声明T类型,对于其中的变量没有智能感知功能.这点很是奇怪, Linq竟然没有强制声明类型.

       21     var lowerThanFive=numbers.Where<int>(i=>i<5);

       22     var lowerThanFive=numbers.Where(i=>i<5);

    以上两种写法竟然都没问题, 显然在下一种写法中变量i 无法获得智能感知的能力. 
    3. numbers.OrderBy(...),在写这个方法时,numbers的智能感知中并没有OrderBy这个方法, 但是编译运行没有问题.
    4. lambda表达式目前不支持多条语句.

    天祺围棋:www.tianqiweiqi.com呵呵

    凡事以大气象去面对,优秀是一种习惯。

  • 相关阅读:
    poj3068
    tyvj1864 [Poetize I]守卫者的挑战
    BZOJ1597 [Usaco2008 Mar]土地购买
    [AtCoder Regular Contest 083] Bichrome Tree
    [LUOGU]3919 【模板】可持久化数组
    [LUOGU]P3701 主席树(假的)
    2018.7.20模拟赛
    [CodeForces]1006F Xor Path
    2018.7.19模拟赛
    [LUOGU]P1373 小a和uim之大逃离
  • 原文地址:https://www.cnblogs.com/greatverve/p/Lambda.html
Copyright © 2011-2022 走看看