在"委托、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 安装gevent报错

    运行pip install gevent报错 错误信息如下 xcrun: error: invalid active developer path (/Library/Developer/Comman ...

  2. 006_mac osx 应用跨屏幕

    一般情况下 mac osx 中一个应用程序只能在一个屏幕上显示,作为从 windows 转过来的用户有点不太习惯,Goolge 后发现还是有解决方案的(虽然不是很好用). 打开 Mac 的系统偏好设置 ...

  3. Java基础84 javaBean规范

    1.javaBean的概述 1.javaBeam(咖啡豆)是一种开发规范,也可以说是一种技术.  2.JavaBean就是一个普通java类,只要符合以下规定才能称作为javaBean:        ...

  4. java 缺憾:异常的丢失

    一.java的异常实现也是又缺陷的,异常作为程序出错的标志决不能被忽略,但它还是可能被轻易地忽略.下了可以看到前一个异常还没处理就抛出下一个异常,没有catch捕获异常,它被finally抛出下一个异 ...

  5. jTessBoxEditor工具进行Tesseract3.02.02样本训练

    1.背景 前文已经简要介绍tesseract ocr引擎的安装及基本使用,其中提到使用-l eng参数来限定语言库,可以提高识别准确率及识别效率. 本文将针对某个网站的验证码进行样本训练,形成自己的语 ...

  6. 原 nc在centos7上的安装和简单使用

    https://blog.csdn.net/qq_16414307/article/details/50291341 https://www.cnblogs.com/rocky-AGE-24/p/69 ...

  7. GitLab备份的创建与恢复

    使用Gitlab一键安装包安装Gitlab非常简单, 同样的备份恢复与迁移也非常简单. 使用一条命令即可创建完整的Gitlab备份: gitlab-rake gitlab:backup:create使 ...

  8. winform解析json

    在使用C#开发爬虫程序时,会遇到需要解析json字符串的情况.对于json字符串可以使用正则表达式的形式进行解析,更为方便的方法是使用Newtonsoft.Json来实现. Nuget添加应用包 在工 ...

  9. 002 @RequestMapping的说明

    一:修饰方法 1.举例 2.效果 二:修饰类 1.测试类 2.index.jsp 3.效果 ---------------- 三:映射请求请求方法 1.使用语法 分别是method 2.Method的 ...

  10. [java] DOS编译 .java 文件得到 .class 文件 并执行 以及使用外部 .jar包 时的命令

    当写一个java文件后,在DOS中进行编译与执行时,如果没有引入外来的包,那情况很简单 例如: public class hello_world { public static void main(S ...