http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 4582|回复: 0

[C#语言基础] .NET中的Lambda表达式与匿名方法

[复制链接]
发表于 2012-9-28 16:33:07 | 显示全部楼层 |阅读模式
在C#2中,由于有了方法组,匿名方法,类型的协变和抗变,使得运用delegate变得很容易,在注册事件时代码变得简单易读,但是在C# 2中,代码仍然有点臃肿,大块的匿名方法会降低代码的可读性,一般我们不会在一条语句中写多个匿名方法。      LINQ产生的一个目的是能够方便的对数据进行管道操作而不失语义。LINQ能够表达对数据进行的各种逻辑操作,LINQ执行时,这些操作实际上都是通过委托来实现的。使用LINQ to Object操作数据时,一条语句中包含多个委托是很常见的,C# 3中的Lambda表达式正式这幕后的功臣,它不仅使得我们能够在一条代码中写多个委托,而且不会丧失代码的可读性。相信用过LINQ的人应该都有这样的体会。
      在很多方面Lambda表达式可以看成是C#2中匿名方法的演变。他们俩的功能是一样的,都使得代码更加清晰和紧凑。另外,Lambda表达式和匿名方法在闭包的特性上是一致的,但是Lambda表达式还有一些小的特性,能够使得代码在大多数情况下更加紧凑。和匿名方法一样,Lambda表达式有着自己的转换规则---表达式的类型并不是一个委托的类型,但是它可以显示或者隐式的转换为一个委托的实例。
      下面来看看Lambda表达式是如何来表示委托的。我们先从一个简单的例子开始。首先我们写一个以String类型为参数,返回Int32类型的值的委托实例。然后演示委托如何一步一步转换为Lambda表达式。
    一、Func<……>泛型委托类型      首先我们要选委托类型,在.NET 3.5中,提供了一系列泛型委托类型。在.NET3.5中有5个名为Func的泛型委托类型。每一个类型里面包含0至4个类型参数。5个Func泛型类型签名如下:
[C#] 纯文本查看 复制代码
TResult Func<TResult>()
TResult Func<T,TResult>(T arg)
TResult Func<T1,T2,TResult>(T1 arg1, T2 arg2)
TResult Func<T1,T2,T3,TResult>(T1 arg1, T2 arg2, T3 arg3)
TResult Func<T1,T2,T3,T4,TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

尖括号中的,都是类型参数,例如,Func<String,Double,Int32> 表示该委托接受两个参数,第一个是String,第二个是Double,返回Int32类型,所有适合该类型的方法都可以使用该委托。Func<String,Double,Int32>等价如下面的委托:
[code=csharp]public delegate Int32 SomeDelegate(String arg1, Double arg2)[/code]
.NET 3.5中还有一个名为Action<……>的泛型委托类,他的用法和Func的差不多,只是他的返回值为void。如果您觉得5个参数不够用的话,在.NET 4.0中,Action<……>和Func<……>的参数扩展到了16个,如Func<T1,……,T16,TResult>,这么多的参数主要是为了支持DLR。
    在我们这个例子中,我们需要一个类型,他接受String作为参数,返回Int32类型的值,所以我们可以使用Func<String,Int32>。
二、转化为Lambda表达式的第一步    根据上面的委托类型,我们可以使用匿名方法创建一个委托实例。如下,该实例返回String参数的长度。
[C#] 纯文本查看 复制代码
Func<String, Int32> returnLength;
returnLength = delegate(String text) { return text.Length; };
Console.WriteLine(returnLength("Hello"));

上面的例子中,将输出5. 上面的以delegate开头的是匿名表达式。现在我们开始对这部分进行转换。最常见的Lambda表达式的形式如下:
[code=csharp](参数类型1 参数名1 [ , 参数类型2 参数名2 ……]) => { 方法内部表达式 }[/code]
=>是在C# 3中引入的,他告诉编译器,我们将使用Lambda表达式,大多数的使用Lambda表达式代表委托的方法都有一个返回值。但在C# 1中,委托通常用于事件,所以很少有返回值。在LINQ中,委托用做数据管道的一部分,使得数据能够进行各种映射,过滤等操作。
    下面我们使用Lambda表达式来表示该委托的实例,代码如下:
[C#] 纯文本查看 复制代码
Func<String, Int32> returnLength;
returnLength = (String text)=> { return text.Length; };
Console.WriteLine(returnLength("Hello"));

上面的例子返回的结果和之前的一样,在大括号中,我们可以写任意表达式,只要返回值为String类型。
三、使用单个表达式作为函数体    前面的例子中,我们使用一对大括号将返回值表达式括起来了。这样做很灵活,你可以在括号内写多条语句,进行各种操作,就像在匿名方法中的那样。但是大多数情况下,通常可以将这个函数体表示为单个表达式,这个表达式的值就是Lambda表达式的值。在这种情况下,我们可以省去左右的大括号和逗号,表达式样子下面的样子。
[C#] 纯文本查看 复制代码
(参数类型1 参数名1 [ , 参数类型2 参数名2 ……]) =>方法表达式

这样,上面例子中的右边部分可以改写为:
[C#] 纯文本查看 复制代码
returnLength = (String text) => text.Length;

现在看起来简洁多了。那参数类型怎么办呢,由于编译器已经知道他是Func<String,Int32>的一个实例,该实例接受一个String类型的参数,所以我们可以直接将参数卸载括号内,从而省略参数类型。
四、隐式类型参数列表    在大多数情况下,编译器能够推断出参数的类型,而不需要我们现实的去声明,因此,Lambda表达是可以改写为:
[C#] 纯文本查看 复制代码
(参数名1 [ ,参数名2 ……]) =>方法表达式

隐式类型参数列表,就是一系列用逗号分隔的参数名称。这些参数类型,要么全部都显示声明类型,要么全部不声明类型让编译器推断,不能一部分显示声明,一部分隐式声明。如果有参数类型为out或者in的话,就必须显示声明参数类型。这样我们的Lambda表达式可以改写为:
[C#] 纯文本查看 复制代码
returnLength = (text) => text.Length;

现在看起来简洁多了。最后唯一一点有点不爽的是,参数有个括号。
五、去掉单参数两侧的括号    当Lambda表达式只有一个参数的额时候,C# 3运行我们省略掉两边的括号,整个Lambda表达式变为下面的形式:
[C#] 纯文本查看 复制代码
(参数名) =>方法表达式

根据这一规则,之前例子中的Lambda表达个可以改为:
[C#] 纯文本查看 复制代码
returnLength = text => text.Length;
  你可能会想,哪有这么多特例啊,参数恰好只有一个,函数主题恰好能用一个表达式表达完。这里是为了展示Lambda表达式如何简化代码提高可读性,很多时候,当大量的这样的情况出现时,使用Lambda表达式能够极大提高代码可读性。现在整个方法可以写成下面这样:
[C#] 纯文本查看 复制代码
Func<String, Int32> returnLength; returnLength = text => text.Length; Console.WriteLine(returnLength("Hello"));
  现在看起来简洁多了,可能第一次觉得这样写怪怪的,就像第一次用匿名方法和LINQ那样,用久了就习惯了。当使用Lambda表达式时,你能够体会到在创建一个委托实例时时多磨的简洁。上面例子中,我们可以把变量text换乘其他名字比如x,在LINQ中经常这样,但是长一点的变量可以更加容易阅读。下图总结了以上的步骤:
QQ截图20120928163421.jpg


1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-12-19 08:28

© 2014-2021

快速回复 返回顶部 返回列表