• 《你不常用的c#之三》:Action 之怪状


    转载自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代码可以看出。

    1. 相关阅读:
      JAVA获取昨天、今天、明天等日期
      IDEA设置调用方法时提示方法上的注释
      Hibernate使用distinct返回不重复的数据,使用group by 进行分组
      SpringBoot 自定义注解
      tailwindcss 使用总结
      nodejs nvm 包管理
      macos NPM 全局安装解决方案
      git 遇到修改github密码导致本地push失败解决方案
      Jupyter 快捷方式设置
      Vue indent eslint缩进webstorm冲突解决
    2. 原文地址:https://www.cnblogs.com/zhaox583132460/p/3406233.html
    Copyright © 2020-2023  润新知