从C#3.0开始,可以使用lambda表达式把实现代码赋予委托。lambda表达式与委托(http://www.cnblogs.com/afei-24/p/6762442.html)直接相关。当参数是委托类型时,就可以使用lambda表达式实现委托引用。

    

        static void Main()
{
string mid = ", middle part,"; Func<string, string> anonDel = param =>
{
param += mid;
param += " and this was added to the string.";
return param;
};
Console.WriteLine(anonDel("Start of string")); }

  lambda运算符“=>” 的左边是参数列表,右边是lambda变量的方法的实现代码。

1.参数
  如果lambda表达式只有一个参数,只写出参数名就可以,像上面的代码。

  如果委托使用多个参数,就需要把参数名放到括号中:
  Func<double, double, double> twoParams = (x, y) => x * y;
  Console.WriteLine(twoParams(3, 2));

  可以在括号中给变量名添加参数类型:
  Func<double, double, double> twoParamsWithTypes = (double x, double y) => x * y;
  Console.WriteLine(twoParamsWithTypes(4, 2));

2.多行代码
  如果lambda表达式只有一条语句,在方法块内就不需要花括号和return语句,因为编译器会添加一条隐形的return语句。
  Func<double, double, double> twoParams = (x, y) => x * y;

  Func<double, double, double> twoParams = (x, y) =>
    {
      retrun x * y;
    }
  如果在lambda表达式的实现代码中有多条语句,就必须添加花括号和return语句:
  Func<string, string> anonDel = param =>
  {
    param += mid;
    param += " and this was added to the string.";
    return param;
  };

3.闭包
  通过lambda表达式可以访问lambda表达式块外部的变量,这称为闭包。闭包是一个很好的功能,但如果使用不当,会很危险。例如:
  int someVal = 5;
  Func<int,int> f = x => x+someVal;
  假定以后修改了变量someVal,于是调用委托f时,会使用someVa的新值:
  someVal = 7;
  f(3);//结果为10而不是8.
  特别是,通过另一个线程调用lambda表达式时,我们可能不知道进行了这个调用,也不知道外部变量的当前值是什么。
  所以在使用闭包时,一定要谨慎!!!

  在lambda表达式访问lambda表达式块外部的变量时,编译器在定义lambda表达式时,编译器会创建一个匿名类,它用一个构造函数来传递外部变量。该构造函数取决于从外部传递进来的变量个数和类型。
  对于lambda表达式Func<int,int> f = x => x+someVal;

    public class AnonymousClass
{
private int someVal;
public AnonymousClass(int someVal)
{
this.someVal = someVal;
} public int AnonymousMethod(int x)
{
retrun x+someVal;
}
}

  使用lambda表达式并调用该方法的时,会创建匿名类的一个实例,并传递调用该方法时变量的值。

4.使用foreach语句的闭包
  先看下面这个例子:
  var values = new List<int>() {10,20,30};
  var funcs = new List<Func<int>>();

  foreach(var val in values)
  {
    funcs.Add(() => val);
  }

  foreach(var f in funcs)
  {
    Console.WriteLine((f()));
  }

  第一条foreach语句添加了funcs列表中每个元素。添加到列表中的函数使用lambda表达式。该lambda表达式使用了一个变量val,该变量在lambda表达式的外部定义为foreach语句的循环变量。第二条foreach语句迭代funcs列表,以调用列表中引用的每个函数。
  在C#5.0之前版本编译这段代码时,会在控制台输出30三次。这是因为,在第一个foreach循环中使用闭包,所创建的函数是在调用时,而不是在迭代时获得val变量的值。在http://www.cnblogs.com/afei-24/p/6738155.html中介绍foreach时讲到编译器会从foreach语句中创建一个while循环。在C#5.0之前版本中,编译器在while循环外部定义循环变量,在每次迭代中重用这个变量。因此,在循环结束时,该变量的值就是最后一次迭代时的值。要想在使用C#5.0之前版本时,输出10,20,30,需要将代码改为使用一个局部变量:
  var values = new List<int>() {10,20,30};
  var funcs = new List<Func<int>>();

  foreach(var val in values)
  {
    var v = val;
    funcs.Add(() => v);
  }

  foreach(var f in funcs)
  {
    Console.WriteLine((f()));
  }

  在C#5.0中,不再需要做这种代码修改。C#5.0会在while循环的代码中创建一个不同的局部循环变量。

C#之lambda表达式的更多相关文章

  1. 你知道C#中的Lambda表达式的演化过程吗?

    那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...

  2. Linq表达式、Lambda表达式你更喜欢哪个?

    什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...

  3. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

  4. Kotlin的Lambda表达式以及它们怎样简化Android开发(KAD 07)

    作者:Antonio Leiva 时间:Jan 5, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin/ 由于Lambda表达式允许更简单的方式建模式 ...

  5. java8中lambda表达式的应用,以及一些泛型相关

    语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public clas ...

  6. 背后的故事之 - 快乐的Lambda表达式(二)

    快乐的Lambda表达式 上一篇 背后的故事之 - 快乐的Lambda表达式(一)我们由浅入深的分析了一下Lambda表达式.知道了它和委托以及普通方法的区别,并且通过测试对比他们之间的性能,然后我们 ...

  7. CRL快速开发框架系列教程二(基于Lambda表达式查询)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  8. Lambda 表达式递归用法实例

    注意: 使用Lambda表达式会增加额外开销,但却有时候又蛮方便的. Windows下查找子孙窗口实例: HWND FindDescendantWindows(HWND hWndParent, LPC ...

  9. Spark中Lambda表达式的变量作用域

    通常,我们希望能够在lambda表达式的闭合方法或类中访问其他的变量,例如: package java8test; public class T1 { public static void main( ...

  10. 释放Android的函数式能量(I):Kotlin语言的Lambda表达式

    原文标题:Unleash functional power on Android (I): Kotlin lambdas 原文链接:http://antonioleiva.com/operator-o ...

随机推荐

  1. python复习。知识点小记

    1.对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符: >>> ord('A') >>> ord('中' ...

  2. 于普通用户启动UAC问题

    在VS中设置UAC级别操作如下: 项目属性-配置属性-连接器-清单文件 1.UAC执行级别: aslnvoker: 权限级别最低,不需要管理员身份. highestAvailable:获取最高权限执行 ...

  3. iOS最好用的引导页

    最近项目结束的时候又要改引导页,之前写的启动页改起来太麻烦了,所以就直接封装一个,功能可能还不是很完善,但是感觉用起来也比较方便,在这里和大家分享一下. 这是github的下载地址:https://g ...

  4. JAVA-随机读写文件

    File类通过使用 . 来获取当前路径,从而取得文件. File f = new File(".\\Res\\Temp.txt"); 或者直接使用空构造函数: File f = n ...

  5. XJOIWinterCampPrecontest1-P2队列

    2 排队2.1 题目有n 个人打水,第i 个人打水需要ai 的时间.有K 个水龙头,你可以随意安排他们打水的顺序以及使用哪一个水龙头,但是每一时刻每一个水龙头只能有一个人使用且一个人一旦开始打水就不能 ...

  6. Access SQL实现连续及不连续Rank排名

    一.关于起因 在Excel中我们经常使用Rank函数对数据进行排名操作.而在Access中我们要进行排名是找不到这个Rank函数的,此时我们需要自己书写VBA代码或者建立SQL查询来完成排序操作. 今 ...

  7. Html5 Canvas笔记(3)-Canvas状态

    p{ font-size: 15px; text-indent: 2em; } .alexrootdiv>div{ background: #eeeeee; border: 1px solid ...

  8. 移动开发必须要弄明白的问题】详解Eclipse转Android Studio

    2015-12-09 13:01:244264浏览3评论 AS出来一年多了,最近才从Eclipse转到AS,但我并不觉得使用Eclipse有多落后,它们都只是一个工具而已,哪个顺手就用哪个,用得好都能 ...

  9. 【Android】沉浸式状态栏实现

    在Android4.4(API 19)及以后的版本中都增加了对沉浸式状态栏的支持,实现起来也很简单,将application的主题稍作修改即可: <style name="AppThe ...

  10. navicat与phpmyadmin做mysql的自定义函数和事件

    自定义函数和事件是mysql一个很方便的功能,navicat在5.1以上版本就支持了自定义函数和事件,phpmyadmim不清楚. 用这个是由于一些简单的事情,没有必要去做一个服务器计划使用 接下来我 ...