Lambda表达式与匿名方法的区别

那么,为什么Lambda表达式比匿名方法写起来要短呢?这种像变戏法一样的手法真的能用吗?有没有重要信息遗漏掉呢?为了回答这些问题,就让我们把匿名方法和Lambda表达式比较一下,看看Lambda表达式究竟怎么写。

 1using System;
 2
 3delegate int SampleDelegate(int x, int y);
 4
 5class Program
 6{
 7  private static void Calculate(int x, int y, SampleDelegate calculator)
 8  {
 9    Console.WriteLine(calculator(x, y));
10  }
11
12  static void Main(string[] args)
13  {
14    // 匿名方法
15    Calculate(1, 2,
16      delegate(int x, int y) { return x + y; }); // 输出:3
17
18    // Lambda表达式
19    Calculate(1, 2, (x, y) => x + y); // 输出:3
20  }
21}
22

List9 匿名方法与Lambda表达式的比较

这段代码中,下述部分分别是匿名方法和Lambda表达式的写法:

匿名方法

delegate(int x, int y) { return x + y; }

Lambda表达式

(x, y) => x + y

字面上比较一下就能发现以下不同:

  • delegate关键字没有了
  • return关键字没有了
  • 指定参数的类型的int没有了
  • 中括号“{ }”没有了
  • 行尾的分号“;”没有了
  • 新出现了“=>”这两个字符

下面,对这些区别,一个一个来解释。

首先,Lambda表达式使用的“=>”,叫“=>运算符”,读作“向~输入”(日本读法,跟国情有关)。在上例中,就读作“向x、y输入x+y”(虽这样说,但如果不习惯也不必勉强这样读,笔者也不爱这样读,忒费劲)。delegate关键字并不是去掉了,如果理解为被“=>”运算符替换了的话可能更容易理解。这就是区分“匿名方法”与“Lambda表达式”的关键字。仅这一点,就从delegate的8个字母减到=>两个字母,少了6个字母呢!(这账算的,也不知是真傻还是精明过头了。对我们C#程序员来说,敲入delegate恐怕要比敲入=>快多了。鬼知道=、>这两个字符在哪个键上,每次都要低头去找,还要按Shift,麻烦!)

其次,return这个关键字,因为Lambda表达式本身就是“表达式”,所有旧没有必要再return了(如果是代码段的话,就又需要return了,后面详述)。例如:

int method() { return 1 + 2; }

这种情况下return还需要。但这种情况:

1 + 2

就不需要再return了。这里去掉return,又减去6个字符。(大汗)

参数类型不需要指定了,有些人可能会担心对于类型检查是不是太草率了,有人可能会窃喜不用再费事去声明类型了,切实这两种人都错了。List 9,Calculate方法的参数是SampleDelegate类型的,SampleDelegate代理的参数是2个int类型的,已经声明过了。所以不用再一次声明,x和y已经可以确定是int类型了。

这里再补充一点,这些其实都不是Lambda表达式所特有的。匿名方法虽确实需要显式的把参数类型写上,返回值的类型却采用了同样方法来推断。反过来说,如果不能够进行这样的推断,那么匿名方法和Lambda表达式都不能使用。类型不确定的场合下,是不能够使用的。这一点要记住。

接下来是中括号{ }和行尾的分号;的省略,其理由其实和return的理由是一样的,因为Lambda表达式本身就是表达式(相反,加上中括号{ }的就是“Lambda语句”,后文详述)。

OK,讲完收功。没什么神奇的,也不损失严密性,但其实现的代码缩短能力却是压倒性的。

Lambda语句(日本人叫Statement型Lambda)

到目前为止见到的Lambda表达式,都是“表达式型的Lambda”。因为其都是按表达式的方法写的而得名。

另外,还有一种内容按语句方式写的“Lambda语句”。它不是简单的表达式。如果要把较长代码写入Lambda的话还是Lambda语句好用。书写方式也简单,就是用中括号括起来就行了。

以下是一个例子:

Code
using System;

class Program
{
  static void Main(string[] args)
  {
    // Lambda语句
    Action<string> method = (filename) =>
      {
        if (filename == null)
          Console.WriteLine("Hello!");
        else
          System.IO.File.WriteAllText(filename, "Hello!");
      };

method(null); // 输出:Hello!
    method("hello.txt"); // 生成hello.txt文件
  }
}

Lambda语句有返回值得情况下就使用return。例如,下面的Lambda表达式换做Lambda语句的话:

表达式形式的Lambda

  (n) => a == n;

语句形势的Lambda

  (n) => { return a == n; };

这个一看就明白了,文字上长了不少。但是,不能写Lambda表达式,只能用Lambda语句的情况下,仅一个return的增加这样的开销还是能够接受的。

以下是日文原文:

ラムダ式と匿名メソッドの違い

 さて、なぜラムダ式は匿名メソッドよりも短く書けるのだろうか。そんな手品のようなことが本当に可能なのだろうか。何か重要な情報が欠落しているのではないだろうか。その疑問に答えるために、匿名メソッドとラムダ式を比較しながらラムダ式の書き方を見てみよう。

using System;

delegate int SampleDelegate(int x, int y);

class Program
{
  private static void Calculate(int x, int y, SampleDelegate calculator)
  {
    Console.WriteLine(calculator(x, y));
  }

static void Main(string[] args)
  {
    // 匿名メソッド
    Calculate(1, 2,
      delegate(int x, int y) { return x + y; }); // 出力:3

// ラムダ式
    Calculate(1, 2, (x, y) => x + y); // 出力:3
  }
}

リスト9 匿名メソッドとラムダ式の比較

 このプログラムの以下の部分がそれぞれ匿名メソッドとラムダ式である。

匿名メソッド
  delegate(int x, int y) { return x + y; }

ラムダ式
  (x, y) => x + y

 この2つを見比べると以下のことが分かるだろう。

  • delegateキーワードが消えた
  • returnキーワードが消えた
  • 引数の型指定(int)が消えた
  • 中カッコ({、})が消えた
  • 文末のセミコロン(;)が消えた
  • 「=>」の2文字が増えた

 以下、これらを1つ1つ検証していこう。

 まず、ラムダ式で使用されている「=>」は「=>演算子」と呼ばれ、「~に入力」と読む。上記の場合、「x、yをx + yに入力」と読む(とはいえ、無理にそう読む必要はない。筆者はいちいち「~に入力」とは読んでいない)。

 delegateキーワードは単に消えたのではなく、=>演算子に置き換えられたと考えると分かりやすいだろう。これらはそれぞれ、「匿名メソッドである」「ラムダ式である」という意図を示す重要な記述である。これによって、delegateの8文字が「=>」の2文字に減って6文字減である。

 次のreturnキーワードだが、ラムダ式はそれ自身が「式」であるため、returnは必要ない(ステートメント・ブロックとして記述する場合はreturn文が必要になる。詳しくは後述)。例えば、

int method() { return 1 + 2; }

にreturnは必要だが、式である、

1 + 2

にreturnは必要ないのと同じである。これでreturnの6文字が減った。

 引数の型指定がないことは、型の厳密なチェックがおろそかになると心配する人や、面倒な型宣言がなくなってアバウトに書けるようになると喜んだ人もいるかもしれないが、どちらもハズレである。リスト9では、Calculateメソッドの引数はSampleDelegateという型であり、SampleDelegateデリゲートの引数はint型が2つと宣言されているので、いちいちラムダ式で宣言しなくとも、xとyはそれぞれint型に確定する。

 念のために補足すると、これはラムダ式固有のものではない。匿名メソッドでは確かに引数は明示的に型を添えて示す必要があったが、戻り値の型に関しては同様の手段により推測されていた。逆にいえば、そのような推測ができない状況では、匿名メソッドもラムダ式も使用できない。型が確定しないアバウトな状態では使えない、ということである。

 次に中カッコが消えた理由と、文末のセミコロンが消えた理由は、returnが消えた理由と同じで、ラムダ式はそれ自身が「式」だからである(逆に、中カッコを付ければラムダ式も「ステートメント型のラムダ」として文を記述できる。詳しくは後述)。

 以上である。タネも仕掛けもなく、厳密さを損なうこともなく、圧倒的な構文の短さを実現している。

ステートメント型のラムダ

 ここまで見てきたラムダ式は、「式形式のラムダ」と呼ばれる。まさに「式」によって内容が記述されるからである。

 一方、内容を文の列として記述する「ステートメント型のラムダ」も存在する。簡単な式ではなく、込み入ったコードを書く場合はこちらの方が便利である。書き方は簡単で、式の代わりに中カッコで囲った文の列を書くだけである。

 以下に、一例を示す。

using System;

class Program
{
  static void Main(string[] args)
  {
    // ステートメント型のラムダ
    Action<string> method = (filename) =>
      {
        if (filename == null)
          Console.WriteLine("Hello!");
        else
          System.IO.File.WriteAllText(filename, "Hello!");
      };

method(null); // 出力:Hello!
    method("hello.txt"); // hello.txtファイルを作成
  }
}

リスト10 ステートメント型のラムダの例

 ステートメント型のラムダが値を返す場合はreturn文を使用する。例えば、以下をステートメント型に変更する場合はこのように修正する。

式形式のラムダ
  (n) => a == n;

ステートメント型のラムダ
  (n) => { return a == n; };

 これを見ると分かるとおり、かなり文字数が増えて冗長な感じになる。しかし、式形式のラムダでは書けず、ステートメント型のラムダが要求されるケースでは、かなり長めのコードを書くことになるため、returnキーワードが増える程度のオーバーヘッドはさほど気にはならない。

转载于:https://www.cnblogs.com/zephrx/archive/2009/09/04/1560286.html

[C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别(日文翻译)...相关推荐

  1. Python入门——第一章 python编程基础

    Python入门 文章目录 Python入门 第一章 python编程基础 1.1 基本输入输出 1.1.1使用print()函数进行简单输出 chr()函数 print()输出到指定文件 print ...

  2. NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译

    NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译 第一章第二节Mapping a class with XML第一 ...

  3. 萌新向Python数据分析及数据挖掘 第一章 Python基础 第三节 列表简介 第四节 操作列表...

    第一章 Python基础 第三节 列表简介 列表是是处理一组有序项目的数据结构,即可以在一个列表中存储一个序列的项目.列表中的元素包括在方括号([])中,每个元素之间用逗号分割.列表是可变的数据类型, ...

  4. Java Lambda 表达式(又名闭包 (Closure)/ 匿名函数 ) 笔记

    Java Lambda 表达式(又名闭包 (Closure)/ 匿名函数 ) 笔记 根据 JSR 335, Java 终于在 Java 8 中引入了 Lambda 表达式.也称之为闭包或者匿名函数. ...

  5. Lambda 表达式详解~Lambda与集合

    我们先从最熟悉的*Java集合框架(Java Collections Framework, JCF)*开始说起. 为引入Lambda表达式,Java8新增了java.util.funcion包,里面包 ...

  6. 【JavaSE】Lambda表达式、接口组成更新、方法引用

    文章目录 1. Lambda表达式 1.1 Lambda表达式初体验 1.2 Lambda表达式的基本格式 1.3 Lambda表达式练习 1.4 Lambda表达式的省略规则 1.5 Lambda表 ...

  7. Java笔记 - 黑马程序员_08(Lambda表达式,接口组成更新,方法引用,类加载器,反射)

    1. Lambda 1.1 函数式编程思想概述 在数学中,函数就是有输入量.输出量的一套计算方案,也就是"数据做操作" 面向对象思想强调"必须通过对象的形式来做事情&qu ...

  8. 蓝桥杯比赛常考算法_备战蓝桥--算法竞赛入门第一章总结

    笔者备战蓝桥杯先打算看完<算法竞赛入门经典>第2版,在这里写下第一章的笔记,供自己和大家参考. 鸡兔同笼问题 原题: 已知鸡和兔的总数量为n,总腿数为m.输入n和m,依次输出鸡的数目和兔的 ...

  9. 【SQL进阶教程】第一章 case表达式

    本系列基于<SQL进阶教程>(如下图)学习,实现了书中代码及练习题代码.PS:电子书请大家各自默默脚本之家. [知识点1]case表达式概述 Case表达式有简单case表达式和搜索cas ...

最新文章

  1. 回望云计算发展 重新解读三种云服务
  2. 一个基于ngrx的计数器例子
  3. CRM Order confirmation form布局
  4. Connect 大会的主题 ---微软大法好
  5. 2020年高考数学试题难吗?历史上最难数学卷不是2003!
  6. html下拉列表兼容性,下拉菜单select样式设置(兼容IE6/IE7/IE8/火狐)
  7. aspose word 转pdf中文乱码_pdf转word——都是乱码!怎么办
  8. 2018 ACM-ICPC Asia Beijing Regional Contest题解
  9. zookeeper教程,docker 安装,命令,python操作zookeeper,分布式队列,分布式锁
  10. 帝国cms 7.5 wap标签大全
  11. Alpha阶段测试报告
  12. hive时空链战_时空链战Chain Strike游戏电脑版下载_时空链战Chain Strike最新电脑版下载_18183手机游戏下载...
  13. 小米12X、小米12、小米12 Pro参数对比
  14. 【图解经典算法题】如何用一行代码解决约瑟夫环问题
  15. 声音的频率与主观听感
  16. Win系统 - 更新卡太久,我能不能强制关机?
  17. jackson-databind 版本升级遇到的问题
  18. H3CSE20200603班-IPv6路由协议
  19. Android 11 微信,QQ ,微博 分享适配
  20. JS 三个值求最大值

热门文章

  1. 互联网时代,还有闷声发大财的吗?
  2. 大家都在讲大数据,大数据是什么呢?
  3. 为什么好多人都要给Typec叫华为充电线?
  4. Cause: java.sql.SQLException: Unknown initial character set index ‘255‘ received from server. Initia
  5. SqlPackage.exe –使用bacpac和PowerShell或Batch技术自动执行SQL Server数据库还原
  6. colock 氟橡胶_橡胶球与玻璃球–任务优先级的隐喻
  7. 【Noip模拟 20161005】公约数
  8. 2018-11-13#Hive外表创建和加载数据
  9. sys模块,subprocess模块
  10. Android Glide数据更新及内存缓存、硬盘缓存清理