在"委托、Lambda表达式、事件系列02,什么时候该用委托"一文中,使用委托让代码简洁了不少。

  1. namespace ConsoleApplication2
  2.  
  3. {
  4.  
  5.     internal delegate bool MyCalculateDelegate(int val);
  6.  
  7.     class Program
  8.  
  9.     {
  10.  
  11.         static void Main(string[] args)
  12.  
  13.         {
  14.  
  15.             IEnumerable<int> source = new List<int>(){2, 3, 4, 5, 6, 7, 8, 9,10, 11};
  16.  
  17.             MyCalculateDelegate del = LessThanFive;
  18.  
  19.             var result = GetNumbers(source, del);
  20.  
  21.             foreach (int n in result)
  22.  
  23.             {
  24.  
  25.                 Console.WriteLine(n);
  26.  
  27.             }
  28.  
  29.         }
  30.  
  31.         static IEnumerable<int> GetNumbers(IEnumerable<int> numbers, MyCalculateDelegate del)
  32.  
  33.         {
  34.  
  35.             foreach (int number in numbers)
  36.  
  37.             {
  38.  
  39.                 if (del(number)) yield return number;
  40.  
  41.             }
  42.  
  43.         }
  44.  
  45.         static bool LessThanFive(int val)
  46.  
  47.         {
  48.  
  49.             return val < 5;
  50.  
  51.         }
  52.  
  53.         static bool LessThanTen(int val)
  54.  
  55.         {
  56.  
  57.             return val < 10;
  58.  
  59.         }
  60.  
  61.     }
  62.  
  63. }
  64.  

可是,以上LessThanFive方法和LessThanTen方法的输入参数、输出类型、以及实现逻辑都是一致的,有没有一种形式可以替代它们?这正是Lambda表达式登场的时候!Lambda表达式是匿名委托,以=>分隔,左边是输入参数,右边是实现过程。

  1. namespace ConsoleApplication2
  2.  
  3. {
  4.  
  5.     internal delegate bool MyCalculateDelegate(int val);
  6.  
  7.     class Program
  8.  
  9.     {
  10.  
  11.         static void Main(string[] args)
  12.  
  13.         {
  14.  
  15.             IEnumerable<int> source = new List<int>(){2, 3, 4, 5, 6, 7, 8, 9,10, 11};
  16.  
  17.             var result = GetNumbers(source, n => n < 5);
  18.  
  19.             foreach (int n in result)
  20.  
  21.             {
  22.  
  23.                 Console.WriteLine(n);
  24.  
  25.             }
  26.  
  27.         }
  28.  
  29.         static IEnumerable<int> GetNumbers(IEnumerable<int> numbers, MyCalculateDelegate del)
  30.  
  31.         {
  32.  
  33.             foreach (int number in numbers)
  34.  
  35.             {
  36.  
  37.                 if (del(number)) yield return number;
  38.  
  39.             }
  40.  
  41.         }
  42.  
  43.     }
  44.  
  45. }
  46.  

以上,使用Lambda表达式又让代码简洁了不少!GetNumbers的实参n => n < 5,就是一个Lambda表达式,它符合委托MyCalculateDelegate的定义,输入参数是整型,输出是bool类型。

其实,lambda表达式n => n < 5是一种"语法糖",内部还是执行了如下代码:

  1.         ......
  2.  
  3.         MyCalculateDelegate del = LessThanFive;
  4.  
  5.         var result = GetNumbers(source, del);
  6.  
  7.         ......
  8.  
  9.         static bool LessThanFive(int val)
  10.  
  11.         {
  12.  
  13.             return val < 5;
  14.  
  15.         }

这一点可以从IL层面看出。使用Reflector进行反编译:

  1. private static void Main(string[] args)
  2.  
  3. {
  4.  
  5.     List<int> <>g__initLocal0 = new List<int>();
  6.  
  7.     <>g__initLocal0.Add(2);
  8.  
  9.     <>g__initLocal0.Add(3);
  10.  
  11.     <>g__initLocal0.Add(4);
  12.  
  13.     <>g__initLocal0.Add(5);
  14.  
  15.     <>g__initLocal0.Add(6);
  16.  
  17.     <>g__initLocal0.Add(7);
  18.  
  19.     <>g__initLocal0.Add(8);
  20.  
  21.     <>g__initLocal0.Add(9);
  22.  
  23.     <>g__initLocal0.Add(10);
  24.  
  25.     <>g__initLocal0.Add(11);
  26.  
  27.     IEnumerable<int> source = <>g__initLocal0;
  28.  
  29.     IEnumerable<int> result = GetNumbers(source, (CS$<>9__CachedAnonymousMethodDelegate2 != null) ? CS$<>9__CachedAnonymousMethodDelegate2 : (CS$<>9__CachedAnonymousMethodDelegate2 = new MyCalculateDelegate(Program.<Main>b__1)));
  30.  
  31.     foreach (int n in result)
  32.  
  33.     {
  34.  
  35.         Console.WriteLine(n);
  36.  
  37.     }
  38.  
  39. }
  40.  

以上,由于n => n > 5符合委托MyCalculateDelegate的定义,在内部创建了一个MyCalculateDelegate类型的委托,然后把一个编译器生成的方法<Main>b__1赋给了委托变量。

  1. [CompilerGenerated]
  2.  
  3. private static bool <Main>b__1(int n)
  4.  
  5. {
  6.  
  7.     return (n < 5);
  8.  
  9. }

<Main>b__1方法是由编译器帮我们自动生成的。

总结:lambda表达式其实是"语法糖",源代码被编译的时候,编译器会自动帮我们生成一个符合委托定义的方法,然后把该方法赋给委托。

“委托、Lambda表达式、事件系列”包括:

委托、Lambda表达式、事件系列01,委托是什么,委托的基本用法,委托的Method和Target属性

委托、Lambda表达式、事件系列02,什么时候该用委托

委托、Lambda表达式、事件系列03,从委托到Lamda表达式

委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理

委托、Lambda表达式、事件系列05,Action委托与闭包

委托、Lambda表达式、事件系列06,使用Action实现观察者模式,体验委托和事件的区别

委托、Lambda表达式、事件系列07,使用EventHandler委托

委托、Lambda表达式、事件系列03,从委托到Lamda表达式的更多相关文章

  1. 委托、Lambda表达式、事件系列05,Action委托与闭包

    来看使用Action委托的一个实例: static void Main(string[] args) { int i = 0; Action a = () => i++; a(); a(); C ...

  2. 委托、Lambda表达式、事件系列07,使用EventHandler委托

    谈到事件注册,EventHandler是最常用的. EventHandler是一个委托,接收2个形参.sender是指事件的发起者,e代表事件参数. □ 使用EventHandler实现猜拳游戏 使用 ...

  3. 委托、Lambda表达式、事件系列06,使用Action实现观察者模式,体验委托和事件的区别

    在"实现观察者模式(Observer Pattern)的2种方式"中,曾经通过接口的方式.委托与事件的方式实现过观察者模式.本篇体验使用Action实现此模式,并从中体验委托与事件 ...

  4. 委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理

    委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链.本篇的话题包括:委托链是怎样形成的,如何调用委托链方法,以及委托链异常处理. □ 调用返回类型为 ...

  5. 委托、Lambda表达式、事件系列02,什么时候该用委托

    假设要找出整型集合中小于5的数. static void Main(string[] args) { IEnumerable<int> source = new List<int&g ...

  6. 委托、Lambda表达式、事件系列01,委托是什么,委托的基本用法,委托的Method和Target属性

    委托是一个类. namespace ConsoleApplication1 { internal delegate void MyDelegate(int val); class Program { ...

  7. Lamda表达式的参数捕获,太酷了

    lamda表达式有了参数捕获这个功能,让Action这个委托变得无所不能.Action委托就是无参数,无返回值的一个代理类型. 它只能对应于下面这种类型的函数声明. public void Funct ...

  8. 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】

    1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...

  9. C# Note2:委托(delegate) & Lambda表达式 & 事件(event)

    前言 本文主要讲述委托和Lambda表达式的基础知识,以及如何通过Lambda表达式实现委托调用,并阐述.NET如何将委托用作实现事件的方式. 参考:C#高级编程 1.什么是委托(delegate)? ...

随机推荐

  1. mac rsync文件传输

    rsync -avz filename servername:/filename --exclude '*.log' --exclude '*.pyc' --exclude '*.db' --excl ...

  2. 解决windows10 里vs2017 直接开始执行提示“此任务要求应用程序有提升的权限”1.

    1.打开vs的安装路径,我的是 C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv\ ,找到  VSLauncher.exe 右击该文 ...

  3. java中URL 的编码和解码函数

    java中URL 的编码和解码函数java.net.URLEncoder.encode(String s)和java.net.URLDecoder.decode(String s);在javascri ...

  4. Python学习三|列表、字典、元组、集合的特点以及类的一些定义

    此表借鉴于他人 定义 使用方法 列表 可以包含不同类型的对象,可以增减元素,可以跟其他的列表结合或者把一个列表拆分,用[]来定义的 eg:aList=[123,'abc',4.56,['inner', ...

  5. WCF服务安全控制之netTcpBinding的用户名密码验证【转】

    选择netTcpBinding WCF的绑定方式比较多,常用的大体有四种: wsHttpBinding basicHttpBinding netTcpBinding wsDualHttpBinding ...

  6. Redis Scan命令

    原地址:https://www.cnblogs.com/tekkaman/p/4887293.html [Redis Scan命令] SCAN cursor [MATCH pattern] [COUN ...

  7. Long-Polling, Websockets, SSE(Server-Sent Event) 之间有什么区别?

    链接:http://www.mamicode.com/info-detail-1327667.html https://www.jianshu.com/p/d3f66b1eb748?from=time ...

  8. 网络协议之TLS

    前言 由于在TCP.UDP等方式传输数据时,数据包有可能被其他人截获,并解析出信息,这就给信息安全带来了很大的挑战.最初的SSL协议被网景公司提出,它不会影响上层协议(如HTTP.电子邮件等),但可以 ...

  9. ubuntu eclipse 找不到jre文件

    一. 把jdk下的jre文件copy到eclipse安装目录 二. 打开eclipse 重新设计library和工作空间

  10. Java编程的逻辑 (15) - 初识继承和多态

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...