C#温故而知新系列 -- 闭包-阿里云开发者社区

开发者社区> rstaryan> 正文

C#温故而知新系列 -- 闭包

简介: 闭包的由来    要说闭包的由来就不得不先说下函数式编程了。近几年函数式编程也是比较火热,我们先来看看函数式编程的一些基本的特性这个有助于我们理解闭包的由来。    函数式编程      函数式编程是一种编程模型,他将计算机运算看做是数学中函数的计算,并且避免了状态以及变量的概念。
+关注继续查看

闭包的由来

   要说闭包的由来就不得不先说下函数式编程了。近几年函数式编程也是比较火热,我们先来看看函数式编程的一些基本的特性这个有助于我们理解闭包的由来。

   函数式编程

     函数式编程是一种编程模型,他将计算机运算看做是数学中函数的计算,并且避免了状态以及变量的概念。这里很明显的指出了函数式编程中最重要的就是函数而且是数学中的函数,比如f(x),数学中的函数最大的特点就是只要是同样的参数x那么我的结果必定是相等的,也就是说我们函数的返回值只是依赖于参数而不依赖于其他状态(比如js中的全局变量就是一个干扰因素);后一句中说避免变量的概念,这句话如果从函数式编程来说不太恰当,因为这句话中的函数意思还是我们在编程语言中所使用的变量也就是一个存储单元,而在函数式编程中变量却是数学中变量的定义是一个值得名称。比如,我们最基本的赋值等式 x = x+1,让我们程序员看这是一个简单的赋值代码,而让学数学的人来说这个等式是根本不成立的。 所以我们在函数式编程中是不允许多次赋值的。而这一句话也是讲述了函数式编程好处的最主要的原因:

   第一点、函数的结果只依赖于参数而不依赖其他状态,这样写的代码很容易进行推理不容易发生错误,极大的方便的单元测试和调试。

   第二点、因为不可变性和无状态,那么我们在处理多个线程之间就不用担心资源的争夺,不需要用锁来保存状态。

   高阶函数

      函数式编程中函数是一等公民,和我们的口号 "万物皆对象"有点相似,在函数式编程中,我们努力用函数来表达所有的事情,当然我们也需要函数可以传过来传过去这就是高阶函数,也就是把函数作为参数或者返回值,继而实现复用,这样即是可以把复用的粒度降到函数。C#语言中也有类似的东西--委托,当然C#中的函数跟函数式编程中的就不一样了,但是有吸收一些函数式编程语言中的特性,比如C#中lamda,Linq。

     关于函数式编程博客园有很多很好的文章介绍我就不详说了,接下来就是引出我们今天的主题--闭包。

    因为函数式编程的基础就是Lambda演算,所以这一节演算我们用Lambda演算来带出我们的主题,关于这个演算我也懂得不是太多,想要入门的同学可以看看这个  点这里

首先定义一个简单的演算

    λx.λy.x+y

如果x为1 y为2 演算过程则为

  ((λx.λy.x+y)1)2=(λy.1+y)2=(1+2)=3

接下来我们用到高阶函数 

   λy . (λx . x + y)

演算过程:

  ((λy . (λx . x + y))1)2=((λx . x + 1))2 = (2+1)=3

可以看到这个演算中外层函数使用的是内层函数,也就是说使用是一个函数作为了计算结果。OK ,我们把内层函数单独拿出来,(λx . x + y),可以很明显的看到如果脱离的上下文呢,我们的y是没有值的,也就是y是没有绑定的,也可以说y对于我们这个函数是自由的! 如果在函数式编程中,在外层函数执行完毕之后我们的y变量就应该被销毁,那么如果我们在内层函数中如果还需要用到y的话怎么办呢? 对于这个问题,设计者则做了其他的处理:如果一个函数返回另一个函数,而被返回函数又需要外层函数的变量时,不会立即释放这个变量,而是允许被返回的函数引用这些变量。支持这种机制的语言称为支持闭包机制,而这个内部函数连同其自由变量就形成了一个闭包(这句话是摘自其他博客,自己难得整理文字。。。)。这就是我们闭包的由来,而我们其他的语言如果有用到函数式编程的思想,并且允许函数来进行传递就会遇到类似的问题,所以各个语言就需要用其自己的方式来实现闭包!

C#中闭包的实现

     从上一节我们也就是能总结出闭包其实就是要执行并且包含自由变量的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境的一个结合。 

然后进入我们的C#编程时刻了,我们就用简单的例子来实现,并且查看编译器生成的代码 看看C#中是怎么实现闭包,毕竟我们也是有委托的 。。。

     首先写一个简单得不能在简单的代码

    

 1 using System;
 2 
 3 namespace closure
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             Console.WriteLine(test(1)(2));
10             Console.ReadKey();
12         }
13 
14         public static Func<int,int> test(int x)
15         {
16             //作用域1
17             return (y) =>  
18             {
19                //作用域2
20                return x + y;
21             };
22         }
23     }
24 }

   可以看到我们test的方法中传入变量x的作用域是在1 在执行匿名函数的时候应该是已经释放在作用域2就不应该存在了,而我们却能准确的得到计算结果    

   

 

  说明我们的变量x确实在作用域2中还存在,接下来我们看看编译器帮我们做了什么事情,

  

 

  可以看到我们的test方法中多了一个对象 <>c__DisplayClass1_0  class_;这个东西的具体定义是啥?

 

   这个很明显了,其实闭包只是编译器帮我们把自由变量封装到了一个对象中供我们作用域外使用,那我们如果去掉作用域2中使用x变量呢?

  

  编译器原来为了自由变量维护的对象没了 。。。结果在意料之中。

 

OK,这篇文章就到此结束了,关于闭包是python中啊 js中啊 或者C#中得用处我就不细说了,博客园中有太多太多的介绍了,希望这边文章对你有帮助,欢迎拍砖!

 

 

 

   

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
使用NAT网关轻松为单台云服务器设置多个公网IP
在应用中,有时会遇到用户询问如何使单台云服务器具备多个公网IP的问题。 具体如何操作呢,有了NAT网关这个也不是难题。
26794 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
10885 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
12076 0
windows server 2008阿里云ECS服务器安全设置
最近我们Sinesafe安全公司在为客户使用阿里云ecs服务器做安全的过程中,发现服务器基础安全性都没有做。为了为站长们提供更加有效的安全基础解决方案,我们Sinesafe将对阿里云服务器win2008 系统进行基础安全部署实战过程! 比较重要的几部分 1.
9161 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
11818 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
4660 0
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
7503 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
4508 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
22405 0
+关注
rstaryan
一直专注于.net领域的技术,希望共同进步
19
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载