• 20 闭包


      20.7 闭包的概念。内层函数引用的外层函数的变量的最终值。
    我们预期的输出是, jiejiep, xiaoyi, zhangzetian
    但是实际我们运行后发现,程序会报错,提示索引超出界限。
    为什么没有达到我们预期的效果呢?让我们再来看一下闭包的概念。内层函数引用的外层函数的变量的最终值。就是说,当线程中执行方法时,方法中的i参数的值,始终是userList.Count。原来如此,那我们该如何
    避免闭包陷阱呢?C#中普遍的做法是,将匿名函数引用的变量用一个临时变量保存下来,然后在匿名函数中使用临时变量。

    	List<UserModel> userList = new List<UserModel>
    	{
    		new UserModel{ UserName="jiejiep", UserAge = 26},
    		new UserModel{ UserName="xiaoyi", UserAge = 25},
    		new UserModel{ UserName="zhangzetian", UserAge=24}
    	};
    
    	for (int i = 0; i < 3; i++)
    	{
    		UserModel u = userList[i];
    		ThreadPool.QueueUserWorkItem((obj) =>
    		{
    			//TODO
    			//Do some process...
    			//...
    			Thread.Sleep(1000);
    			//UserModel u = userList[i];
    			Console.WriteLine(u.UserName);
    		});
    	}
    

    5.5 匿名方法中的捕获变量

            static MethodInvoker CreateInvoker()
            {
                int count = 5;
                MethodInvoker ret = delegate
                  {
                      Console.WriteLine(count);
                      count++;
                  };
                ret();
                return ret;
            }
    

    5.5.4 捕获变量的延长生存期

            static void Main(string[] args)
            {
                MethodInvoker m = CreateInvoker();
                m();
                m();
    
                Console.ReadKey();
            }
            static MethodInvoker CreateInvoker()
            {
                int count = 5;
                MethodInvoker ret = delegate
                  {
                      Console.WriteLine(count);
                      count++;
                  };
                ret();
                return ret;
            }
    

    由循环的初始部分声明的变量只被实例化一次。这很容易弄错!如果你想捕获循环变量在一次特定的循环迭代中的值,必须在循环内部引入另一个变量,并将循环变量的值复制给它,再捕捉那个新变量

            static void Main(string[] args)
            {
                MethodInvoker m = CreateInvoker();
                m();
                m();
    
                Console.ReadKey();
            }
            static MethodInvoker CreateInvoker()
            {
                int count = 5;
                MethodInvoker ret = delegate
                  {
                      Console.WriteLine(count);
                      count++;
                  };
                ret();
                return ret;
            }
    

      

  • 相关阅读:
    JasperReport html 导出
    mysql 序列号生成器 (自定义函数)
    [Java][Spring]Spring事务不起作用 问题汇总
    序列 mysql
    订单编号
    Mybatis
    SNMP 配置
    Gradle 1.12用户指南翻译——第三十八章. Eclipse 插件
    cocos2dx2.0 与cocos2dx3.1 创建线程不同方式总结
    Android实战简易教程-第二十八枪(Uri转String型实例)
  • 原文地址:https://www.cnblogs.com/kikyoqiang/p/10152532.html
Copyright © 2020-2023  润新知