这是一篇很经典的文章,解决了工作中一些使用过但是又不太明白的知识点,今天终于弄明白了。花了一晚上重新整的,坚决要分享出来!!!

那得从很久很久以前说起了,记得那个时候...

懵懂的记得从前有个叫委托的东西是那么的高深难懂。

委托的使用

例一:

public delegate void AddDelegate();
public class Program
{
public Program()
{
AddDelegate add = new AddDelegate(Add);
}
public void Add()
{
Console.Write("hello");
}
}

什么是委托?

个人理解:用来传递方法的类型。(用来传递数字的类型有int、float、double,用来传递方法的就有委托

例二:

 public delegate void Callback();
class Program
{
public Program()
{
SendMail(SavaLogOK, SaveLogErr);
}
public void SendMail(Callback sentResult, Callback errorAction)
{
//...发送邮件...
if (true)
sentResult(); //发送成功
else
errorAction(); //发送失败
} public void SaveLogErr()
{ }
public void SavaLogOK()
{ }
}

又经过了很久很久...

匿名方法

很多时候委托接收的方法是一次性的或者方法体是非常简单的...

例三:

 public delegate int AddDelegate(int a, int b);
public class Program
{
public Program()
{
AddDelegate addTest = new AddDelegate(Add);
addTest(,);//执行方法
}
public int Add(int a, int b)
{
return a + b;
}
}

我们可以写成:

 public delegate int AddDelegate(int a, int b);
public class Program
{
public Program()
{
AddDelegate addTest = new AddDelegate(delegate(int a, int b) { return a + b; });
} }

有没有发现我们每次都要定义委托,很多时候签名可能是一样的。这样就没有必要定义重复的。

然后又过了很久很久...

Func和Action

可能老大也觉得我们每次定义委托有点傻,所以干脆在框架内一次定义好所有可能用到的委托。那千变万化的方法签名怎么可能定义得全?没关系,定义成泛型的不就可以了吗。

先说Func:

 public delegate int AddDelegate(int a, int b);//这种委托不用在定义
public class Program
{
public Program()
{
// AddDelegate addTest = new AddDelegate(delegate(int a, int b) { return a + b; });
Func<int, int, int> addTest = new Func<int, int, int>(delegate(int a, int b) { return a + b; });
} }

细心的朋友可能看到了,Func相对于AddDelegate多定义了一个int。多出了的那个是指的是返回类型。我们F12看对应的定义:

  // 摘要:
// 封装一个具有两个参数并返回 TResult 参数指定的类型值的方法。
//
// 参数:
// arg1:
// 此委托封装的方法的第一个参数。
//
// arg2:
// 此委托封装的方法的第二个参数。
//
// 类型参数:
// T1:
// 此委托封装的方法的第一个参数类型。
//
// T2:
// 此委托封装的方法的第二个参数类型。
//
// TResult:
// 此委托封装的方法的返回值类型。
//
// 返回结果:
// 此委托封装的方法的返回值。
[TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

关于上面Func的写法我们可以简写成:(语法糖而已,编译后还是注释的代码

  // AddDelegate addTest = new AddDelegate(delegate(int a, int b) { return a + b; });
// Func<int, int, int> addTest = new Func<int, int, int>(delegate(int a, int b) { return a + b; });
Func<int, int, int> addTest = delegate(int a, int b) { return a + b; };

再看Action:

 class Program
{
public Program()
{
SendMail(SavaLogOK, SaveLogErr);
}
public void SendMail(Action sentResult, Action errorAction)
{
//...发送邮件...
if (true)
sentResult(); //发送成功
else
errorAction(); //发送失败
} public void SaveLogErr()
{ }
public void SavaLogOK()
{ }
}

提醒:以后如果我们写代码的时候如果写到到delegate...,你要马上想到是否可以用Func或者Action来代替呢?C#4中的Action和Func有16个参数,足够你用了。

我们等了又等,又过了好久好久...

Lambda的诞生

  public Program()
{
Func<int, int, int> addTest = delegate(int a, int b) { return a + b; };
Func<int, int, int> addTest2 = (int a, int b) => { return a + b; };
}

我XX,这TM就是亲兄弟啊。直接去掉delegate关键字,然后加一个=>就成了lambda表达式了。(=>读作goes to

我们继续简化:

 public Program()
{
Func<int, int, int> addTest = (int a, int b) => { return a + b; };
Func<int, int, int> addTest2 = (a, b) => { return a + b; };
}

丢掉参数类型也是可以的,因为强大的VS可以根据泛型委托Func自己推断出来参数类型。

还可以简化吗?当然:

                 Func<int, int, int> addTest = (int a, int b) => { return a + b; };
Func<int, int, int> addTest2 = (a, b) => { return a + b; };
Func<int, int, int> addTest3 = (a, b) => a + b;

return关键字也不要了,大括号也不要了。(当然,方法体只有单条语句才能怎么做

现在看起来已经非常接近我们平时用的Lambda表达式了。

如果传入参数只有一个的话,我们还可以继续简化:

Func<int, int> func = (a) => * a;

func = a => * a;

这就是我们平时见得最多的lambda长相了。

要长成这样也是有要求的:

  1. 只能有一个传入参数
  2. 方法体只能只一条语句。

关于第1点,lambda我们平时用得较多的是基于IEnumerable或IQueryable,所以只能有一个参数也就满足了。

关于第2点,我们使用扩展方法的链式编程来解决。

如:(用链式来解决第二点)

 public Program()
{
Func<IEnumerable<string>, IEnumerable<string>> fun = t =>
t.Where(v => v.Length > ).Reverse().OrderBy(v => v.Length).ToList();
}

从此,我们过上了幸福的生活...

借《深入理解C#》中的一图:

小知识:(异步Lambda)

 Func<Student, Task<bool>> func = async t =>
{
await Task.Delay();//等待100毫秒
return false;
};

结束:

本文简短的说了下lambda表达式在C#中的一步步演化。说的不一定对,轻拍!

FROM :http://www.cnblogs.com/zhaopei/p/5769782.html

Lambda表达式的诞生过程的更多相关文章

  1. 你知道C#中的Lambda表达式的演化过程吗

    你知道C#中的Lambda表达式的演化过程吗? 阅读目录 委托的使用 匿名方法 Func和Action Lambda的诞生 那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西 ...

  2. 【转】你知道C#中的Lambda表达式的演化过程吗?

    [转]你知道C#中的Lambda表达式的演化过程吗? 那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传 ...

  3. 你知道C#中的Lambda表达式的演化过程吗?

    那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...

  4. 函数进化到Lambda表达式的三过程

    假如我们想要从一个整型数组中取出其中是奇数的选项,其实现方式有很多, 接下来通过三种方法的对比理解Lambda表达式的用途,需要了解的朋友可以参考下         //声明委托类型 public d ...

  5. 个人理解的Lambda表达式的演化过程

    之前在组内进行过相关分享,为防止以后再单独整理,故在此将自己的PPT内容存放下. 所以,多数代码都是以图片的方式展现. 委托 什么是委托? 定义:委托是方法的抽象,它存储的就是一系列具有相同签名和返回 ...

  6. C#中的Lambda表达式的演化过程

    原文:http://www.cnblogs.com/zhaopei/p/5767631.html

  7. lambda表达式之进化

    前言 在C#我们可以自定义委托,但是C#为什么还要内置泛型委托呢?因为我们常常要使用委托,如果系统内置了一些你可能会用到的委托,那么就省去了定义委托,然后实例化委托的步骤,这样一来既使代码看起来简洁而 ...

  8. 理解Lambda表达式和闭包

    了解由函数指针到Lambda表达式的演化过程 Lambda表达式的这种简洁的语法并不是什么古老的秘法,因为它并不难以理解(难以理解的代码只有一个目的,那就是吓唬程序员) #include " ...

  9. [c#菜鸟]lambda表达式

    what 一.定义 Lambda 表达式是一种可用于创建 委托 或 表达式目录树 类型的 匿名函数 .通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数.(微软) 理 ...

随机推荐

  1. ucos实时操作系统学习笔记——任务间通信(互斥锁)

    想讲一下ucos任务间通信中的mutex,感觉其设计挺巧妙,同sem一样使用的是event机制实现的,代码不每一行都分析,因为讲的没邵贝贝老师清楚,主要讲一下mutex的内核是如何实现的.可以理解互斥 ...

  2. ucos实时操作系统学习笔记——内核结构和任务创建

    对于ucos实时操作系统,邵贝贝的那本书已经写得很详细了,我因为之前不深的研究过ucos,所以在这里做一个笔记,写一些个人对该操作系统的理解,仅仅是个人理解,如果有人看到这边随笔有不对的地方,望给我指 ...

  3. [转]Java实现定时任务的三种方法

    在应用里经常都有用到在后台跑定时任务的需求.举个例子,比如需要在服务后台跑一个定时任务来进行非实时计算,清除临时数据.文件等.在本文里,我会给大家介绍3种不同的实现方法: 普通thread实现 Tim ...

  4. Windows Server 2008 小操作汇总

    用惯了Windows2003,去配置2008的时候还真有点摸不着头脑.干脆把有用到的都列在这里,方便后续查找. 一.安装IIS.Telnet      点击:开始 -> 管理工具 -> 服 ...

  5. ASP.NET Web API Model-ModelMetadata

    ASP.NET Web API Model-ModelMetadata 前言 前面的几个篇幅主要围绕控制器的执行过程,奈何执行过程中包含的知识点太庞大了,只能一部分一部分的去讲解,在上两篇中我们看到在 ...

  6. Redis集群搭建与简单使用

    介绍安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. 两台虚拟机都是 CentOS ,一台 ...

  7. [MongoDB] 32Bit构建上文件大小限制问题

    一. 问题概述 今天看看爬虫抓取的数据,发现数据无法插入,首先想到的就是32Bit构建的文件大小限制问题,检查一下还真的是.本文把整个检查问题,解决问题的过程记录下来. 问题:     "s ...

  8. WCF学习之旅—WCF服务的WAS寄宿(十二)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) 八.WAS宿主 IIS ...

  9. JavaScript高级编程 (2) - HTML 与 JavaScript

    向HTML 页面中插入JavaScript 的主要方法,就是使用<script>元素.这个元素由Netscape 创造并在Netscape Navigator 2 中首先实现.后来,这个元 ...

  10. mysql数据库开发常见问题及优化

    mysql 数据库是被广泛应用的关系型数据库,其体积小.支持多处理器.开源并免费的特性使其在 Internet 中小型网站中的使用率尤其高.在使用 mysql 的过程中不规范的 SQL 编写.非最优的 ...