zoukankan      html  css  js  c++  java
  • 浅谈.NET中闭包

    什么是闭包

        闭包可以从而三个维度来说明。在编程语言领域,闭包是指由函数以及与函数相关的上下文环境组合而成的实体。通过闭包,函数与其上下文变量之间建立起关联关系,上下文变量的状态可以在函数的多次调用过程中持久保持。从作用域而言,私有变量的生命周期被延长,函数调用所生成的值在下次调用时仍被保持。从安全性而言,闭包有利于信息的隐蔽,私有变量只在该函数内可见。

    .NET中的闭包

        说起闭包,可对会想起JavaScript。在JavaScript语言中,闭包可以说是无处不在。同样,.NET中也有闭包。只不过实现方式和JavaScript不太一样。

    通常而言,形成闭包有一些值得总结的非必要条件:

    • 嵌套定义函数
    • 匿名函数
    • 将函数作为参数或返回值

        在.NET中,函数并不是第一级成员,所以并不能像JavaScript那样通过嵌套子函数的方式实现闭包。但.NET可以通过匿名委托形成闭包。

     delegate void HelloDelegate();
            static void Main(string[] args)
            {
                string str = "Hello World!";
    
                HelloDelegate hello = delegate()
                {
                    Print(str);
                };
            }
    
            private static void Print(string str)
            {
                Console.WriteLine(str);
            }

    反编译上面的IL代码:

    S)TV14[6U~P`@NY6G~$}2UK

    如上图所示,编译器自动生成了一个内部类,变量strb变成这个类的字段,即使创建该变量的方法(Main)执行结束,该变量也不会释放,而是在所有回调函数执行之后才被GC回收。这就是.NET实现闭包的原理。

    闭包带来的问题

    如下面代码:

     static void Main()
            {
                IList<Action> actions = new List<Action>();
    
                for (int i = 0; i < 5; i++)
                {
                    actions.Add(() => Console.WriteLine(i));
                }
    
                foreach (var action in actions)
                {
                    action();
                }
            }

    先猜猜输入的值是什么,如果猜的0、1、2、3、4的话就错了。应该全是4。那为什么呢?因为闭包具有延迟的和数据共享的特性,只有当调用action()方法时才会获取i的值,这是i的值经过i++已经变成4,又因为所有的action都会获取同一个i值,所以最后输出的值都为4。

    那怎么解决呢?通常解决方法时在循环中加入中间量。

                for (int i = 0; i < 5; i++)
                {
                    int j = i;
                    actions.Add(() => Console.WriteLine(j));
                }

    N}$8(%MX}MUPZ}YVDY3GGJB

  • 相关阅读:
    【转】logback logback.xml常用配置详解(三) <filter>
    【转】logback logback.xml常用配置详解(二)<appender>
    【转】logback logback.xml常用配置详解(一)<configuration> and <logger>
    webhook: requestbin
    Docker: repository, image, container
    Python 知识点
    MySql: 常见sql语句
    MySql: 常见错误
    Linux 网络命令必知必会之 tcpdump,一份完整的抓包指南请查收!
    这些好用的 Chrome 插件,提升你的工作效率
  • 原文地址:https://www.cnblogs.com/Khadron/p/Closure.html
Copyright © 2011-2022 走看看