转载自csdn:http://blog.csdn.net/robingaoxb/article/details/6199891

例1:

 

public static void Main()
{
List<Action> ls = new List<Action>();
for (int i = 0; i < 10; i++)
{
ls.Add(() => Console.WriteLine(i));
}
foreach (Action action in ls)
{
action();
} Action a1 = ls[0] as Action;
Action a2 = ls[1] as Action;
Console.WriteLine(object.ReferenceEquals(a1,a2));
Console.Read();
}

输出结果:

例2:

public static void Main()
{
List<Action> ls = new List<Action>();
for (int i = 0; i < 10; i++)
{
int tp = i;
ls.Add(() => Console.WriteLine(tp));
}
foreach (Action action in ls)
{
action();
} Action a1 = ls[0] as Action;
Action a2 = ls[1] as Action;
Console.WriteLine(object.ReferenceEquals(a1,a2));
Console.Read();
}
则结果为:
为啥呢?我们来用windbg分析下:

对于例1,我们观看堆上的Action对象(System.Action )只有一个,
heap上的列表:

6c27166c 1 32 System.Action

你的foreach里其实都是循环的一个action
所以最后的时候是10(i的最后值)

而例2中则有10个
action对象在heap上的列表:

6c27166c 10 320 System.Action

10个,每个action里引用一个tp,
heap列表:

Address MT Size
01451790 6c27166c 32
014517dc 6c27166c 32
01451808 6c27166c 32
01451834 6c27166c 32
01451860 6c27166c 32
014518bc 6c27166c 32
014518e8 6c27166c 32
01451914 6c27166c 32
01451940 6c27166c 32
014519bc 6c27166c 32

随便看一个Address,比如这个01451914 ,dump出来的值是

MT Field Offset Type VT Attr Value Name
79102290 4000001 4 System.Int32 1 instance 7 tp

看到没,此时的tp还存在,值为7。

为了验证,我们可以

Action a1 = ls[0] as Action;
Action a2 = ls[1] as Action;
Console.WriteLine(object.ReferenceEquals(a1,a2));

第一个例子true,第二个(tp) 则为false。

看来我用windbg有点越俎代庖。

更确切说是VS编译器优化的问题,从MSIL代码可以看出。

《你不常用的c#之三》:Action 之怪状的更多相关文章

  1. struts2 笔记01 登录、常用配置参数、Action访问Servlet API 和设置Action中对象的值、命名空间和乱码处理、Action中包含多个方法如何调用

    Struts2登录 1. 需要注意:Struts2需要运行在JRE1.5及以上版本 2. 在web.xml配置文件中,配置StrutsPrepareAndExecuteFilter或FilterDis ...

  2. Spark常用函数讲解之Action操作

    摘要: RDD:弹性分布式数据集,是一种特殊集合 ‚ 支持多种来源 ‚ 有容错机制 ‚ 可以被缓存 ‚ 支持并行操作,一个RDD代表一个分区里的数据集RDD有两种操作算子:         Trans ...

  3. 笔记01 登录、常用配置参数、Action访问Servlet API 和设置Action中对象的值、命名空间和乱码处理、Action中包含多个方法如何调用

    Struts2登录 1. 需要注意:Struts2需要运行在JRE1.5及以上版本 2. 在web.xml配置文件中,配置StrutsPrepareAndExecuteFilter或FilterDis ...

  4. Informatica 常用组件Lookup之三 关系和平面文件查找

    创建查找转换时,您可以选择使用关系表或平面文件作为查找源. 关系查找 使用关系表作为查找源来创建查找转换时,您可以使用 ODBC 连接到查找源并导入表定义作为查找转换的结构. 仅可对关系查找使用以下选 ...

  5. Informatica 常用组件Aggregator之三 使用排序输入

    可以使用排序输入选项改善聚合转换性能.使用排序输入时,PowerCenter 会假定所有数据已按组排序.PowerCenter 读取某组的行时,它将执行聚合计算.需要时,它会将组信息存储在存储器中.要 ...

  6. Informatica 常用组件Filter之三 创建FIL

    在 Designer 中,切换到 Mapping Designer 并打开映射. 选择"转换-创建". 选择"过滤器转换",然后输入新的转换名称.过滤器转换的命 ...

  7. 《你不常用的c#之XX》

    你不常用的c#之一>:略谈unsafe http://blog.csdn.net/robingaoxb/article/details/6199508 <你不常用的c#之二>:略谈G ...

  8. C#中常用的系统内置委托

    在公共语言运行时(CLR)环境中系统为我们内置了一些常用的委托,包括Action类的委托.Func类的委托.Predicate<T>委托.Comparison<T>委托等等.以 ...

  9. Android Action Bar简介

    Android Action Bar简介 Design: Action Bar Action Bar是在屏幕顶端的一部分内容,通常在整个app进行中都保持存在. 它提供了几个关键的功能: 1.使得重要 ...

随机推荐

  1. MySQL优化器cost计算

    记录MySQL 5.5上,优化器进行cost计算的方法. 第一篇: 单表的cost计算 数据结构: 1. table_share: 包含了表的元数据,其中索引部分: key_info:一个key的结构 ...

  2. POJ_2392_Space_Elevator_(动态规划,背包)

    描述 http://poj.org/problem?id=2392 磊方块,每种方块有数量,高度,以及该种方块所能处在的最高高度.问最高磊多高? Space Elevator Time Limit: ...

  3. React入门1

    React教程 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...

  4. VM Depot 登陆中国!

     发布于 2014-03-24 作者 陈 忠岳 今天我很高兴地向大家宣布,来自微软开放技术(上海)有限公司的首个产品 VM Depot 正式在中国发布!VM Depot是为Windows Azur ...

  5. Git push 时每次都需要密码的疑惑

    2015.1.13更新: 在本地搭建Git服务器时,也是有每次操作需要密码的情况. 是因为每次做推送动作时,Git需要认证你是好人.所以需要密码. 可以在 /home/username/.ssh/au ...

  6. jQuery技术内幕预览版.pdf1

    第一章 总体构架 jQuery模块可以分为3部分:入口模块.底层支持模块和功能模块 浏览器功能测试模块提供了针对不同浏览器功能和bug的测试结果,其它模块基于测试结果解决浏览器之间的兼容性问题 回调函 ...

  7. Linux趣谈

    要解释操作系统是如何工作的,首先可以用这几个关键字来简单地概括一下:冯诺依曼.堆栈机制和中断机制. 提到冯诺依曼很显然就是在说存储程序了,这大概是计算机能够运行最为基础的条件,属于基石级别的.它的基本 ...

  8. h264码流分析及其工具

    总的来说H264的码流的打包方式有两种,一种为annex-b byte stream format的格式,这个是绝大部分编码器的默认输出格式,就是每个帧的开头的3~4个字节是H264的start_co ...

  9. Centos系统python2.x升级python3.x

    1. Centos7初始安装的python版本为2.7.5 2.下载最新的python3.5.2,解压到/usr/local/src 3. 配置.编译.测试.安装(根据软件的README说明) ./c ...

  10. 3.3FactoryMethod——工厂方法

    意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类.FactoryMethod使一个类的实例化延迟到其子类. 其实在抽象工厂模式中,经过改进后的模式就是工厂方法模式,所以不多说了,上UML图 ...