当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > C#教程:作为委托的Lambda表达式

ASP.NET
asp.net css注释的影响
ASP.NET与数据库相关技巧
关于HtmlForm控件
三色交替的下拉列表框
精通ASP.NET中弹出窗口技术
ASP.NET Forums与现有系统整合方案示例
ASP.NET操作IIS中的虚拟目录
DataGrid与SQL Server 2000数据绑定
如何让Web应用程序在Client端实现导出报表功能
如何保证web app中的Send Email线程稳定性
关于用ASP.Net识别远程主机服务器种类
ASP.NET中上传下载文件
提高ASP.NET性能的方法
asp.net StreamReader 创建文件
asp.net如何生成图片验证码(简单)
一个.net 压缩位图至JPEG的代码
简单的SQL Server数据库数据读取与数据操作
获取网站的RSS聚合到自己的网页
.Net程序中整站通用的防SQL注入函数
asp.net生成缩略图及给原始图加水印的函数

ASP.NET 中的 C#教程:作为委托的Lambda表达式


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 38 ::
收藏到网摘: n/a

作为委托的Lambda表达式

从很多方面看, Lambda表达式可以被看成是C# 2中匿名方法的进化. 几乎没有什么匿名方法能做而Lambda表达式不能做的事情, 而Lambda表达式几乎总是能提供更好的可读性且更简洁. 特别的, lambda表达式和匿名方法捕获变量的行为是完全一致的. 在两者多数的显式行为当中并没有存在太多的不同——不过lambda表达式拥有大量的快捷方式, 这在很多常规情况下使得代码更加简洁. 与匿名方法一样, lambda表达式也拥有自己特殊的转换规则——表达式本身的类似并不是一个委托类型, 但其可以通过多种方法被隐式或显式转换成为一个委托实例. 术语匿名函数(anonymous function)覆盖了匿名方法和lambda表达式——因为在很多案例中两者都可以应用相同的转换规则.

接下来我们将从一个简单的例子开始, 首先我们将使用匿名方法. 我们将会创建一个委托实例, 其带有一个string类型的参数并且返回int作为结果(计算string的长度). 首先我们选择使用委托类型. 幸运的是.NET 3.5拥有一系列的泛型委托类型可以帮助我们.

Func<…>委托类型

.NET 3.5的System命名空间下有5个泛型Func委托类型. Func并没有什么特别之处——仅仅是让你方便的拥有了一些预定义的泛型委托, 它们可以适用于多种情况. 每一个委托签名分别拥有0到4个参数, 其类型就是参数本身被赋予的类型, 最后一个参数则是返回值的类型. 以下是所有Func委托类型的签名:

 1: public delegate TResult Func<TResult>()
 2: public delegate TResult Func<T,TResult>(T arg)
 3: public delegate TResult Func<T1,T2,TResult>(T1 arg1, T2 arg2)
 4: public delegate TResult Func<T1,T2,T3,TResult>
 5: (T1 arg1, T2 arg2, T3 arg3)
 6: public delegate TResult Func<T1,T2,T3,T4,TResult>
 7: (T1 arg1, T2 arg2, T3 arg3, T4 arg4)

例如, Func<string, double, int>等价于一个来自于下面代码的委托类型:

 1: delegate int SomeDelegate(string arg1, double arg2)

Action<…>提供了等价的功能, 唯一的区别就是其没有任何的返回值. 单一单数的Action存在于.NET 2.0中, 其他的全部都是.NET 3.5中新引入的。因为我们的例子将会拥有一个string参数, 并且返回int类型, 因此我们将使用Func<string,int>.

首次转换到lambda表达式

现在我们知道了委托类型, 我们可以首先使用匿名方法创建委托实例, 如下所示:

 1: Func<string,int> returnLength;
 2: returnLength = delegate (string text) { return text.Length; };
 3: Console.WriteLine (returnLength("Hello"));

执行结果控制台打印出”5″, 与我们期望的一样, 接下来让我们尝试将它转换为lambda表达式. 最冗长的lambda表达式格式为:

(explicitly-typed-parameter-list) => { statements }

=>是C# 3中新引入的, 其告诉编译器我们正在使用lambda表达式. 多数时候, lambda表达式会和一个带有nonvoid返回类型的委托一起使用. 在C# 1中, 委托通常是被事件使用而很少返回值, 虽然lambda表达式也可以同样适用, 但更多时候当它们需要返回值时用lambda表达式看起来将更加高雅.

下面的代码与前面的例子结果一致, 只不过是用的lambda表达式:

 1: Func<string,int> returnLength;
 2: returnLength = (string text) => { return text.Length; };
 3: Console.WriteLine (returnLength("Hello"));

当读到lambda表达式的时候, 我们可以将=>想像成为”goes to”, 因此上述代码可以被理解成text goes to text.length. 在匿名方法中给定的规则同样适用于lambda表达式: 你不能从一个lambda表达式中尝试返回一个void的返回类型. 目前为止我们并没有节省太多的空间而且让代码及其容易的阅读, 现在让我们开始使用一些快捷方式.

使用单一表达式作为主体

目前为止我们使用了一整块的代码去返回值, 这是非常灵活的, 因为我们可以使用多行语句, 执行循环, 在代码块内部的多个地方返回值等等, 与匿名方法一样. 然而很多时候我们只需要一个单一的表达式就可以, 它的执行值就是整个lambda表达式的值. 在这些案例中, 我们可以仅仅指定表达式本身, 没有任何的大括号, 返回语句和分号. 其格式为:(explicitly-typed-parameter-list) => expression

在我们的例子中, 这意味着我们的lambda表达式变为:

 1: (string text) => text.Length

现在, 这看起来已经开始变得简单, 那么, 参数类型呢? 编译器已经知道Func<string, int>需要的是一个string的参数, 因此我们能够仅仅命名该参数…

隐式类型的参数列表

多数时候, 即使你没有显式指明, 编译器依然可以猜测参数类型. 在这些案例中, 我们可以将lambda表达式写成这样:

(implicitly-typed-parameter-list) => expression

一个隐式类型的参数列表就是一个用逗号分开的名称列表, 你不能将两种不同方式组成的方式混合在一起——要吗他们都是隐式的, 要吗他们都是显式的. 另外, 如果有任何的参数是out或者ref类型的参数, 你只能使用显式类型参数. 在我们的例子中没有什么问题, 因此我们的lambda表达式变为:

 1: (text) => text.Length

现在代码已经变得非常简短——已经没有什么太多东西我们可以进一步剔除的了. 虽然参数看起来有一点冗长.

单一参数的快捷方式

当lambda表达式仅仅需要一个参数, 并且该参数可以是隐式类型, C# 3允许我们省略圆括号, 如下:

parameter-name => expression

因此我们的表达式最后将变成:

 1: text => text.Length

你可以会好奇为什么lambda表达式会有这么多特殊的规则——例如, 语言的其他部分并不会去关心方法拥有一个参数或多个参数. 然后, 这看起来似乎很特别的例子实际上是及其常见的, 而且从参数列表当中移除圆括号对于提高可读性是很有意义的, 特别是在一小段代码当中拥有多个lambda表达式的时候. 值得一提的是你还是可以像其他表达式那样使用圆括号, 如果你确实想这么做的话. 有时候, 当你想把lambda表达式赋值给一个变量或者属性的时候, 这对于提高可读性是有帮助的——否则, 等号可能会让人有点混淆, 下面的代码使用了这种做法:

 1: Func<string,int> returnLength;
 2: returnLength = (text => text.Length);
 3: Console.WriteLine (returnLength("Hello"));

一开始你可能会觉得上面的代码有一点点难以阅读, 这与匿名方法第一次出现的时候是一样的, 直到开发人员开始习惯使用它们. 当你开始习惯使用lambda表达式的时候, 你一定会感激它们是多么的简洁方便. 难以想象还有更短更清晰的方法可以用于创建委托实例. 我们当然可以将变量名从text改为x, 实际上, 在LINQ当中, 这是很常用的, 然而, 更长的名字给阅读人员带来了更多的信息.