.NET Lambda表达式的语义:字符串列表范例

开发 后端
本文通过一个字符串列表范例,介绍了.NET Lambda表达式的语义特征。“语义”是指代码所表现出来的含义,说的更通俗一些,便是指一段代码给阅读者的“感觉”如何。

.NET Lambda表达式的“语义”

Lambda表达式的增强在于“语义”二字。“语义”是指代码所表现出来的含义,说的更通俗一些,便是指一段代码给阅读者的“感觉”如何。为了说明这个例子,我们还是使用示例来说明问题。

这个例子是这样的:“请写一个方法,输入一个表示整型的字符串列表,并返回一个列表,包含其中偶数的平方,并且需要按照平方后的结果排序”。很简单,不是吗?相信您一定可以一蹴而就:

  1. static List< int> GetSquaresOfPositive(List< string> strList)  
  2. {  
  3.     List< int> intList = new List< int>();  
  4.     foreach (var s in strList) intList.Add(Int32.Parse(s));  
  5.  
  6.     List< int> evenList = new List< int>();  
  7.     foreach (int i in intList)  
  8.     {  
  9.         if (i % 2 == 0) evenList.Add(i);  
  10.     }  
  11.  
  12.     List< int> squareList = new List< int>();  
  13.     foreach (int i in evenList) squareList.Add(i * i);  
  14.  
  15.     squareList.Sort();  
  16.     return squareList;  
  17. }  
  18.  

我想问一下,这段代码给您的感觉是什么?它给我的感觉是:做了很多事情。有哪些呢?
1. 新建一个整数列表intList,把参数strList中所有元素转化为整型保存起来。
2. 新建一个整数列表evenList,把intList中的偶数保存起来。
3. 新建一个整数列表squareList,把evenList中所有数字的平方保存起来。
4. 将squareList排序。
5. 返回squareList。

您可能会问:“当然如此,还能怎么样?”。事实上,如果使用了Lambda表达式,代码就简单多了:

.NET Lambda表达式的语义:写法范例

  1. static List< int> GetSquaresOfPositiveByLambda(List< string> strList)  
  2. {  
  3.     return strList  
  4.         .Select(s => Int32.Parse(s)) // 转成整数  
  5.         .Where(i => i % 2 == 0) // 找出所有偶数  
  6.         .Select(i => i * i) // 算出每个数的平方  
  7.         .OrderBy(i => i) // 按照元素自身排序  
  8.         .ToList(); // 构造一个List  
  9. }  

配合.NET 3.5中定义的扩展方法,这段代码可谓“一气呵成”(在实际编码过程中,老赵更倾向于把这种简短的“递进式”代码写作一行)。那么这行代码的“语义”又有什么变化呢?在这里,“语义”的变化在于代码的关注点从“怎么做”变成了“做什么”。这就是Lambda表达式的优势。

在第一个方法中,我们构造了多个容器,然后做一些转化,过滤,并且向容器填充内容。其实这些都是“怎么做”,也就是所谓的“how (to do)”。但是这些代码并不能直接表示我们想要做的事情,我们想要做的事情其实是“得到XXX”,“筛选出YYY”,而不是“创建容器”,“添加元素”等操作。

在使用Lambda表达式的实现中,代码变得“声明式(declarative)”了许多。所谓“声明式”,便是“声称代码在做什么”,而不像“命令式(imperative)”的代码在“操作代码怎么做”。换句话说,“声明式”关注的是“做什么”,是指“what (to do)”。上面这段声明式的代码,其语义则变成了:
1. 把字符串转化为整数
2. 筛选出所有偶数
3. 把每个偶数平方一下
4. 按照平方结果自身排序
5. 生成一个列表

至于其中具体是怎么实现的,有没有构造新的容器,又是怎么向容器里添加元素的……这些细节,使用Lambda表达式的代码一概不会关心——这又不是我们想要做的事情,为什么要关心它呢?

虽然扩展方法功不可没,但我认为,Lambda表达式在这里的重要程度尤胜前者,因为它负责了最关键的“语义”。试想,“i => i * i”给您的感觉是什么呢?是构造了一个委托吗(当然,您一定知道在这里其实构造了一个匿名方法)?至少对我来说,它的含义是“把i变成i * i”;同样,“i => i % 2 == 0”给我的感觉是“(筛选标准为)i模2等于零”,而不是“构造一个委托,XXX时返回true,否则返回false”;更有趣的是,OrderBy(i => i)给我的感觉是“把i按照i自身排序”,而不是“一个返回i自身的委托”。这一切,都是在“声明”这段代码在“做什么”,而不是“怎么做”。

没错,“类型推演”,“省略括号”和“省略return关键字”可能的确都是些“细斜的功能,但也正是这些细微之处带来了编码方式上的关键性改变。

以上就通过一个字符串列表的范例,介绍了.NET Lambda表达式的语义特征。

【编辑推荐】

  1. 使用.NET 3.5 Lambda表达式实现委托
  2. 各版本.NET委托的写法回顾
  3. C# Actor模型开发实例:网络爬虫
  4. 强类型和Actor:ActorLite的演示
  5. C#的Tag Message回顾:繁琐而危险
责任编辑:yangsai 来源: 老赵点滴
相关推荐

2009-08-10 09:41:07

.NET Lambda

2009-08-10 17:11:34

.NET 3.5扩展方Lambda表达式

2010-01-05 14:45:58

.NET Framew

2009-09-15 15:18:00

Linq Lambda

2022-12-05 09:31:51

接口lambda表达式

2009-09-09 13:01:33

LINQ Lambda

2012-06-26 10:03:58

JavaJava 8lambda

2009-08-10 10:06:10

.NET Lambda

2009-09-11 09:48:27

Linq Lambda

2024-03-25 13:46:12

C#Lambda编程

2009-09-17 10:40:22

Linq Lambda

2009-09-17 09:44:54

Linq Lambda

2009-09-15 17:30:00

Linq Lambda

2009-08-27 09:44:59

C# Lambda表达

2009-11-11 14:19:39

ADO.NET数据列

2009-07-09 09:51:07

Lambda表达式C#

2009-09-09 17:14:17

Linq lambda

2013-04-07 15:44:26

Java8Lambda

2013-04-10 10:58:19

LambdaC#

2020-10-16 06:40:25

C++匿名函数
点赞
收藏

51CTO技术栈公众号