在《C#高级编程》一书中提到通过Lambda表达式可以访问Lambda表达式块外部的变量 ,这是一个很好的功能(类似Js中的 闭包)。但是如果没有正确的使用,会非常危险。

比如下面的事例中

int someVal  = 5;

Fun<int, int> f = x => x + someVal;

Console.WriteLine(f(3));

我们这个表达式的本意是返回一个数x+5的结果。所以f(3)的结果应该是 3 + someVal = 8。

但是如果以后在不经意中修改了someVal的值,则会出现我们意想不到的结果。

比如:

someVal = 7;

Console.WriteLine(f(3));

此时的打印的结果是10。

特别是当通过多个线程调用Lambda时,我们可能不知道此时someVal的值到底是多少,从而导致不可预知的结果,所以要慎重使用。

那么,在Lambda表达式中使用外部变量的原理是什么呢。

原来,在运行Lambda表达式时,编译器会创建一个匿名类,他可以通过构造函数来传递外部变量。该构造函数的参数取决于外部传递进来的变量个数。对于上面的表达式,匿名类如下所示:

public class AnonymousClass     {

    private int someVal;

 public AnonymousClass(int someVal)         {             this.someVal = someVal;         }

public int Anonymous(int x)         {             return x + someVal;         }

}

这样就可以理解为什么Lambda表达式可以使用外部变量了。

关于Lambda表达式访问外部变量的更多相关文章

  1. 让boost.variant支持lambda表达式访问

    前言 之前写个过一篇博客叫<浅谈boost.variant的几种访问方式>,里面讲到了可以通过访问者方式来获取variant的值,但是在重载函数operator()里面只能够获取varia ...

  2. ios中block访问外部变量的一些注意点

    Block类型是一个C级别的语法和运行机制.它与标准的C函数类似,不同之处在于,它除了有可执行代码以外,它还包含了与堆.栈内存绑定的变量.因此,Block对象包含着一组状态数据,这些数据在程序执行时用 ...

  3. C++ lambda 表达式传递的变量默认不可变

    我遇到例如以下问题: int count=0; listener->onTouchMoved=[count](Touch* t,Event* e){ count++; log("onT ...

  4. JavaScript中子函数访问外部变量的方法

    我们在写web页面时,肯定会经常遇到下面这种情况: <body> <div class="btns-wrapper"></div> <sc ...

  5. Java8初体验(一)lambda表达式语法

    感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com 本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人也是刚刚开始学习Java8,所以文中肯定有错误和理解 ...

  6. Java8特性详解 lambda表达式 Stream

    1.lambda表达式 Java8最值得学习的特性就是Lambda表达式和Stream API,如果有python或者javascript的语言基础,对理解Lambda表达式有很大帮助,因为Java正 ...

  7. Java8学习笔记----Lambda表达式 (转)

    Java8学习笔记----Lambda表达式 天锦 2014-03-24 16:43:30 发表于:ATA之家       本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人 ...

  8. lambda表达式2

    1.lambda表达式 Java8最值得学习的特性就是Lambda表达式和Stream API,如果有python或者javascript的语言基础,对理解Lambda表达式有很大帮助,因为Java正 ...

  9. Java8之lambda表达式

    一.什么是lambda表达式? Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码 ...

随机推荐

  1. Windows下使用XManager访问Ubuntu 11.04的设置方法

    1.Download the attached file and upload it to the server. And, enter the following command to update ...

  2. 刚子扯谈:源于Chanel的图片描述

    文/刚子 2013年8月9日 北京晴 猴晒猴晒 开片语:真心不知道今天该分享点啥?先扯几句牢骚,我个人认为对朋友也够意思,虽然他们有的时候挺操蛋的,虽然还简称哥们儿,虽然还一起交流,但已经变成了无谓的 ...

  3. c++编程中的后缀

    .a 静态库 (archive) .C.c.cc.cp.cpp.cxx.c++ C++源代码(需要编译预处理) .h C或者C++源代码头文件 .ii C++源代码(不需编译预处理) .o 对象文件 ...

  4. android 常用调用系统功能

    1.从google搜索内容 Intent intent = new Intent(); intent.setAction(Intent.ACTION_WEB_SEARCH); intent.putEx ...

  5. strcpy()、memcpy()、memmove()、memset()的内部实现

    一直想知道 strcpy().memcpy().memmove().memset()的内部实现 strcpy(), 字符串拷贝. char *strcpy(char *strDest, const c ...

  6. vb.net中让控件内容为空(Control类)

    在平常的敲系统中大家有没有遇到需要让Textbox控件或者其他的控件的显示内容为空,以前直接的做法是直接等于空值,如果此类控件有很多,都需要空值,难道都要设置一下它的值为空嘛,显然这是一个笨办法,有没 ...

  7. java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值

    在上一篇文章中.我们列出了计算java对象大小的几个结论以及jol工具的使用,jol工具的源代码有兴趣的能够去看下.如今我们利用JDK中的sun.misc.Unsafe来计算下字段的偏移地址,一则验证 ...

  8. vertical-align:middle的居中细节调整

    使用vertical-align:middle可以让行级元素垂直居中,但这个居中是以文字的中线来计算的,而文字的中线在不同的字体上不同,甚至相同的字体在不同的浏览器上显示的都不同.所以直接使用vert ...

  9. 关于用exec来执行存储过程中,参数带有引号的解决方法

    比如:exec 存储过程名 要带有引号的参数 这样写的时候是传不进引号的,可以选定一种字符来表示引号,在存储过程中再进行转换: @test=replace(replace(@test,char(39) ...

  10. (跨平台)cocos2d-x C++ or Object-C(前端)调用C# webservices(后台),实现交叉编译到Android/IOS/WinPhone等移动终端设备

    1.2014年4月2号算是正式找到自己的实习工作-杭州美迪软件有限公司(移动物联事业部)合作于:四川管家婆总部移动终端代理,由于在校选编程专业语言C#和在浙大网新培训课程(C#.Asp.net开发)缘 ...