Lambda高手之路第一部分
转http://www.cnblogs.com/lazycoding/archive/2013/01/06/2847574.html
介绍
Lambda表达式是使代码更加动态,易于扩展并且更加快速(看完本文你就知道原因了)的强有力的工具。也可以用来降低潜在的错误。同时可以利用静态输入和智能提示,就像VS里一样。
Lambda表达式在.net framework 3.5中提出来。并且在LINQ和ASP.NET MVC内部的一些技术中扮演了相当重要的角色。如果你考虑一下ASP.NET MVC中各类控件的实现。你就发现。奥妙就是他们大多使用了Lambda表达式。和Lambda表达式一起,使用Html扩展方法将会使得在后台创建模型 成为可能。
本文会讲到如下的知识。
1.简短的介绍-Lambda表达式是什么,以及为什么和匿名方法不同(之前我们使用的)
2.走近Lambda表达式的性能-在哪些情况下比起标准方法,Lambda会提高/损失性能
3.深入-Lambda表达式在MSIL代码中是什么样
4.一些来自JS世界的模式映射到C#中
5.那些能够提高性能,并且代码看起来相当舒服的使用Lambda的情况。
6.一些我提出的新模式-当然有可能别人也提出来了。但这是我的思考结果。
如果你期望本文是一篇入门教程我可能要让你失望了,除非你真的很优秀并且很聪明,当然我不是这种人,所以我也想提前声明一下:为了读懂这篇文章你可能需要C#的一些高级知识,并且对C#比较了解。
你应该期望本文试着解释一些事情给你,也会解释一些有趣的问题,至少对我来说是这样的。最后我会展示一些实际的例子和模式,如我所说,Lambda表达式简化了很多情况。因此写显式的模式很有用。
背景知识-什么是Lambda表达式
在C#1.0中,委托被提出了,它使得传递函数成为可能,一句话就是委托就是强类型的函数指针,但委托比指针更强大。一般传递一个函数需要如下几步。
1. 写一个委托(就像一个类)包含返回类型和参数类型
2. 使用委托作为某一个函数的参数类型,这样,该函数就可以接受和委托描述的有着相同签名的函数了
3. 将一个委托类型的函数传递给委托,创建一个委托实例。
如果听起来很复杂,确实本来很复杂,但这是必需的。(虽然不是造火箭,但是比你认为的要更多的代码),然而步骤三不是必需的,编译器会为你做他,但是步骤1和2却是必不可少的。
幸运的是C#2.0出现了泛型,现在我们也可以写泛型类,方法,更重要的是,泛型委托,然而,直到.net framework 3.5的时候。微软意识到实际上只有两种泛型委托(当然有一些不同的重载),会覆盖99%的使用情况:
1.Action 没有任何输入参数,也没有输出参数。
2.Action<t1,…t16> 需要1-16个参数,没有输出参数。
3.Func<t1….t16,tout>需要0-16个参数,一个输出参数
Action和其对应的泛型版本(仅仅是一个动作,执行一些事情)返回void的时候。Func则可以返回最后一个参数指定的类型,通过这两个委托类型,我们事实上,大部分情况下。前面提到的三步中的第一部就不用写的。而第二步仍然需要。
那么如果我们想要运行代码的时候怎么做呢。在C#2.0中问题已经可以解决了。在这个版本里。我们可以创建委托方法,也就是一个匿名方法,然后这个语法一直未能流行起来,一个相当简化的匿名方法的版本类似这样:
Func<double, double> square = delegate (double x) {
return x * x;
}
为了提高这种语法,欢迎来到Lambda表达式的国度。首先,这个Lambda名字怎么来的?事实上。来自于数学上的λ演算,更准确的说他是数学中 一个正式的系统。用于通过变量绑定和替换来进行表达式计算,所以我们有0-N个输入参数和一个返回值,而在编程中,也可以没有返回值
我们看一下Lambda表达式的一些例子
//编译器可以识别,然后就可以通过dummyLambda();来调用了
var dummyLambda = () => { Console.WriteLine("Hallo World from a Lambda expression!"); }; //可以通过类似 double y = square(25);来使用
Func<double, double> square = x => x * x; //可以通过类似double z = product(9, 5);来使用
Func<double, double,double> product = (x, y) => x * y; //可以通过类似printProduct(9, 5);来使用
Action<double, double> printProduct = (x, y) => { Console.Writeline(x * y); }; //可以通过类似var sum = dotProduct(new double[] { 1, 2, 3 }, new double[] { 4, 5, 6 });
Func<double[], double[], double> dotProduct = (x, y) => {
var dim = Math.Min(x.Length, y.Length);
var sum = 0.0;
for(var i = 0; i != dim; i++)
sum += x[i] + y[i];
return sum;
}; //可以通过类似 var result = matrixVectorProductAsync(...);使用
Func<double[,], double[], double[]=""> matrixVectorProductAsync = async (x, y) => {
var sum = 0.0;
/* do some stuff ... */
return sum;
};
从上面的代码段里我们可以学到一些东西
- 如果我们只有一个输入参数,我们可以省略()
- 如果我们有一个输入参数,并且向返回一个,那么我们可以省略{}和return关键字
- 我们可以让我们的Lambda表达式异步执行,只要加上async关键字就可以了
- Var关键字一般都不可以用,只有在极少的情况下有才可以。
当然我们可以使用像平常那样使用var,如果我们指定了参数类型,这是可选的。因为类型可以从委托的类型中推断出来。而下面的情况都是错误的。请看下面的例子
var square = (double x) => x * x; var stringLengthSquare = (string s) => s.Length * s.Length; var squareAndOutput = (decimal x, string s) => {
var sqz = x * x;
Console.WriteLine("Information by {0}: the square of {1} is {2}.", s, x, sqz);
};
大部分基本情况我们都知道。但是有些相当cool的东西(这使得他们在很多情况下很有用),我们考虑下面的代码片段
var a = 5;
var multiplyWith = x => x * a;
var result1 = multiplyWith(10); //50
a = 10;
var result2 = multiplyWith(10); //
这是可以的。因此你可以使用其他的变量。这比你想象的要更特殊。因为这里出现了捕获变量。这使得出现了一个闭包,考虑下面的情况。
void DoSomeStuff()
{
var coeff = 10;
var compute = (int x) => coeff * x;
var modifier = () => {
coeff = 5;
}; var result1 = DoMoreStuff(compute); ModifyStuff(modifier); var result2 = DoMoreStuff(compute);
} int DoMoreStuff(Action computer)
{
return computer(5);
} void ModifyStuff(Action modifier)
{
modifier();
}
猜猜看这段代码会发生什么。首先我们创建了一个局部变量。和两个lambda表达式,第一额Lambda表达式展示在其他局部区域里访问局部变量是 可以的。这已经很让人难以置信了。这意味着我们想要保护一个变量,但事实上他仍然可以在其他方法里被访问。而不论方法是被定义在内部还是其他类的里。
而第二个Lambda表达式则模拟了一个Lambda表达式可以修改外部域变量。这意味着我们可以在其他方法里修改我们的局部变量,仅仅需要传一个 在对应域里创建好的Lambda表达式就可以了。因此,我认为闭包有点魔幻的色彩了。就像并行编程一样。可能导致未期望的结果。就像在并行编程中的竞争情 况。
Lambda高手之路第一部分的更多相关文章
- Lambda高手之路第二部分
转http://www.cnblogs.com/lazycoding/archive/2013/01/06/2847579.html 闭包的影响 为了展示闭包的影响,我们看下面这个例子. var bu ...
- Lambda高手之路第三部分
转http://www.cnblogs.com/lazycoding/archive/2013/01/06/2847587.html 背后的秘密-MSIL 通过著名的LINQPad,我们可以更深入的查 ...
- 【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(2)
把下载下来的"hadoop-2.2.0.tar.gz"复制到"/usr/local/hadoop/"文件夹下并解压: 改动系统配置文件,改动~/.bashrc文 ...
- 安卓高手之路之 ClassLoader
我不喜欢那些泛泛而谈的去讲那些形而上学的道理,更不喜欢记那些既定的东西.靠记忆去弥补思考的人,容易陷入人云亦云的境地,最后必定被记忆所围困,而最终消亡的是创造力.希望这个高手之路系列能够记录我学习安卓 ...
- ClassLoader使用记录《安卓高手之路》
我不喜欢那些泛泛而谈的去讲那些形而上学的道理,更不喜欢记那些既定的东西.靠记忆去弥补思考的人,容易陷入人云亦云的境地,最后必定被记忆所围困,而最终消亡的是创造力.希望这个高手之路系列能够记录我学习安卓 ...
- 云计算分布式大数据Hadoop实战高手之路第八讲Hadoop图文训练课程:Hadoop文件系统的操作实战
本讲通过实验的方式讲解Hadoop文件系统的操作. “云计算分布式大数据Hadoop实战高手之路”之完整发布目录 云计算分布式大数据实战技术Hadoop交流群:312494188,每天都会在群中发布云 ...
- [js高手之路] es6系列教程 - 对象功能扩展详解
第一:字面量对象的方法,支持缩写形式 //es6之前,这么写 var User = { name : 'ghostwu', showName : function(){ return this.nam ...
- [js高手之路]深入浅出webpack系列2-配置文件webpack.config.js详解
接着上文,重新在webpack文件夹下面新建一个项目文件夹demo2,然后用npm init --yes初始化项目的package.json配置文件,然后安装webpack( npm install ...
- [js高手之路]Vue2.0基于vue-cli+webpack Vuex用法详解
在这之前,我已经分享过组件与组件的通信机制以及父子组件之间的通信机制,而我们的vuex就是为了解决组件通信问题的 vuex是什么东东呢? 组件通信的本质其实就是在组件之间传递数据或组件的状态(这里将数 ...
随机推荐
- 7款Linux下阅读PDF的阅读器。
5款Linux下阅读PDF的阅读器.1. Mupdf:link 2. Adobe Reader:link 3. Foxit Reader:link 4.Evince:link 5. Okular:li ...
- JNI 详细解释
JNI事实上,Java Native Interface缩写,那是,java本地接口.它提供了许多API实现和Java和其它语言的通信(主要是C&C++). 或许不少人认为Java已经足够强大 ...
- OCP-1Z0-042-V12.39-51题
51.Which two statements regarding archive log destinations are true? 题目解析: A(正确)因为:.归档日志最多可以配置10个 B和 ...
- java web解决表单重复提交问题
我们大家再进行web开发的时候,必不可少会遇见表单重复提交问题.今天就来给总结如何解决表单提交问题,欢迎大家交流指正. 首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提 ...
- 1.1.4-学习Opencv与MFC混合编程之---画图工具 画椭圆
源代码地址:http://download.csdn.net/detail/nuptboyzhb/3961690 1. 增加‘椭圆’菜单项,设置属性,添加类向导: 2. 编辑消息处理函数, ...
- HDU 3328 Flipper (stack)
最近着手打基础,做做STL的题目,虽然一般STL题目难度不大,但需要加快速度的准确率............................. 本题有N张牌,一开始每个位置一张(正面朝上或者朝下),有 ...
- UVA11552------FEWEST FLOPS------区间型的DP
题目地址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- AIX用户管理
用户和组管理 /etc/passwd /etc/security/.profile /etc/security/limits /etc/security/passwd ...
- python 站点爬虫 下载在线盗墓笔记小说到本地的脚本
近期闲着没事想看小说,找到一个全是南派三叔的小说的站点,决定都下载下来看看,于是动手,在非常多QQ群里高手的帮助下(本人正則表達式非常烂.程序复杂的正则都是一些高手指导的),花了三四天写了一个脚本 须 ...
- 论文阅读笔记 - Mesos: A Platform for Fine-Grained ResourceSharing in the Data Center
作者:刘旭晖 Raymond 转载请注明出处 Email:colorant at 163.com BLOG:http://blog.csdn.net/colorant/ 更多论文阅读笔记 http:/ ...