C#2.0 委托
委托
委托是一个非常不错的设计,允许我们把方法做为参数传递,实现了开放閉放原则。在方法中我们只要有一个委托占位,调用者就可以传入符合签名的方法来做不同的操作,这也面向对象开发中多态的魅力。
但是在C#1.0的时候,委托写起来实际上是非常复杂的,首先我们要声明一个委托,然后再写一个符合委托签名的方法。再创建委托实例。然后才是调用,比如下面一个简单的例子,我要在winform程序中用户按了按键后我需要彈出一个消息
因为委托的声明已经内置了,也就是KeyPressEventHandler所以我不用去写。简单一看似乎挺简洁,但是在winForm程序中会有着大量的事件,有些事件可能处理的方式非常简单,但是我们需要去相应的写一个方法。这也是比较头疼的问题。下面我们来看如何优化这个代码
方法组
在这面我们创建了一个委托实例,在C#1.0中,要同时指定委托类型和方法(操作)也就是如下图
而在C#2.0中支持从方法组到一个兼容委托的隐式转换,也就是如果方法签名和委托声明完全相同,那么就不必再去new一个委托。这时代码就变成了
但是有些方法并不是可以进行隐式转换的,如果方法需要一个Delegate类型的参数,那么我们的方法就不适用了,比如Invoke方法。这些我们就要显示转换
协变与逆变
很多人都以为这是在4.0中才支持的,因为那时有了泛型的可变性。不过这个委托的可变性完全不同。
在winform中给我们内置很多的委托类型,比如上面用到的KeyPressEventHandler,还有MouseEventHandler,他们实际上区别不大,只是参数类型不同。第一个参数类型是KeyPressEventArgs,第二个是MouseEventArgs。
不同的事件对应不同的处理,这是没有问题的。但是我们可能会有不同的事件同样的处理这种需求。在C#1.0中很遺憾是没有办法的。而在C#2.0中我们可以使用逆变来解决这个问题
KeyPressEventArgs与MouseEventArgs都派生与EventArgs类型。实际上EventArgs的派生类有多达数百个。
我们只需要有一个具有EventAgrs类型的方法,就可以这么去做
一个返回类型为基类的委托,我们想要用子类去实例化这个委托,这在之前是不可能的。而在C#2.0中,这已经没有任何问题
匿名方法
在C#2.0中設計者也意识到了创建一个委托的步骤过于繁瑣,我们要有一个完整的方法,然后再创建委托实例进行调用,在C#2.0中则出现了匿名方法来帮助我们简化这一流程(3.0中的拉姆达则更加的方便)
下面就是一个简单的匿名方法创建委托实例的例子,拿到一个字符串然后去除两边空格打印出来
虽然我们创建的是一个委托方法,但是编译成IL后每个匿名方法都会创建一个方法,会在匿名方法所在的类生成一个方法不过方法名则是乱七八糟的,不过也不是给程序员去看的。
闭包
使用方法就会使用到变量,对于匿名方法来说,分为外部变量与局部变量。很容易理解,外部变量就是匿名方法外声明的变量,而局部变量就是匿名方法内声明的变量。
如果匿名方法没有使用任何外部变量,那么则相安无事。如果使用了外部变量,那么它就是被捕获的外部变量。在匿名方法内对该变量的操作是有效的!
为什么要说闭包,是因为匿名方法会在特成的情况下延长变量的生命周期,为什么这么说呢,大家都知道委托是方法的类型,可以把方法作为委托进行返回,如果一个方法里有一个委托实例,使用的是匿名方法并且捕获了外部变量,然后把这个委托实例进行返回。这时就形成了一个闭包
这时如果去看IL会发现创建了一个新的类去容纳i变量,这也是为什么方法结束后i变量仍然存在的原因,还有一点需要注意的,外部变量只有一个,如果多个匿名方法捕获了它,那么这些匿名方法使用的都是一个变量,局部变量则没有这个问题
循环中创建的变量,每个委托捕获到的都是不同的变量
我们需要牢記的是
- 補获的是变量,百不是创建委托初值时它的值
- 捕获的变量生命周期被延长,至少和捕捉它的委托一样长
- 多个委托可以捕获同一个变量
- 必要时创建额外的类型来保存捕获变量
C#2.0 委托的更多相关文章
- 委托,匿名函数和lambda表达式
很早之前就接触到了委托,但是一直对他用的不是太多,主要是本人是菜鸟,能写的比较高级的代码确实不多,但是最近在看MSDN微软的类库的时候,发现了微软的类库好多都用到了委托,于是决定好好的研究研究,加深一 ...
- C#—委托分析
1.简单委托示例 using System; using System.Collections.Generic; using System.Linq; using System.Text; names ...
- C# 语言规范_版本5.0 (第1章 介绍)
1. 介绍 C#(读作“See Sharp”)是一种简洁.现代.面向对象且类型安全的编程语言.C# 起源于 C 语言家族,因此,对于 C.C++ 和 Java 程序员,可以很快熟悉这种新的语言.C# ...
- C#6.0语言规范(一) 介绍
C#(发音为“See Sharp”)是一种简单,现代,面向对象,类型安全的编程语言.C#源于C语言系列,对C,C ++和Java程序员来说很熟悉.EC#International将EC#标准化为ECM ...
- C# Language Specification 5.0 (翻译)第一章 引言
C#(念作 See Sharp)是一种简单.现代.面向对象并且类型安全的编程语言.C# 源于 C 语言家族,因此 C.C++ 和 Java 工程师们能迅速上手.ECMA 国际[1](ECMA Inte ...
- C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数
一.隐式类型var 从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,编译器自动推断类型. 1.var类型的局部变量必须赋予初始值,包括匿名 ...
- C#指南,重温基础,展望远方!(11)C#委托
委托类型表示对具有特定参数列表和返回类型的方法的引用. 通过委托,可以将方法视为可分配给变量并可作为参数传递的实体. 委托类似于其他一些语言中的函数指针概念,但与函数指针不同的是,委托不仅面向对象,还 ...
- C#中委托的发展与匿名函数
匿名函数(C# 编程指南) 匿名函数是一个“内联”语句或表达式,可在需要委托类型的任何地方使用. 可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数. 共有两种匿名函数 ...
- jquery2.0.3 全部源码
/*! * Includes Sizzle.js 选择器,独立的库 * http://sizzlejs.com/ */ (function( window, undefined ) { //" ...
随机推荐
- RSP小组——团队冲刺博客六
RSP小组--团队冲刺博客六 冲刺日期:2018年12月18日 前言 各成员今日(12.18)完成的任务 李闻洲,赵乾宸代码合并 马瑞蕃图形后续支持,编写博客,燃尽图 蒋子行会议记录 各个成员的任务安 ...
- Do-Now—团队冲刺博客三
Do-Now-团队 冲刺博客三 作者:仇夏 前言 不知不觉我们的项目已经做了三个多礼拜了,团队冲刺博客也写到了这第三篇,看着一个基本成型的APP安装在自己的手机上,一种喜悦感油然而生.好了,现在来看看 ...
- vs中 VMDebugger未能加载导致异常
,纠结了许久的一个问题,终于找到了解决 vs中 VMDebugger未能加载导致异常 错误号:80004005 搜了好多,没有一个给出完美的答案. 解决办法:工具->导入和导出设置,重置一下 ...
- 资源验证(Modified)
Last-Modified : 上次修改时间 配合 If-Modified-Since 或者 If-Unmodified-Since (请求头携带) 对比上次修改时间对资源进行验证 Etag验证 数 ...
- CSS水平垂直居中!
总结一下,最经典的面试题 分两种情况,宽高确定和不定宽高 (一)宽高确定 初始条件如下: 1. 绝对定位 + 负margin 里面的盒子相对于父盒子绝对定位,距离上面和左边分别为50%,此处的50%是 ...
- xampp访问phpmyadmin访问不了
我的xampp版本是xampp-linux-x64-5.6.15-2-installer.run, 浏览器输入“我的ip/phpmyadmin”出现如下问题: Access forbidden! Ne ...
- 使用curl上传图片的方法
关键:当参数名为"@绝对路径",这时 CURL 會幫你做 multipart/form-data 編碼 实现方法: $params = array( 'file' => '@ ...
- vue创建状态管理(vuex的store机制)
1:为什么说要是永远状态管理 在使用 Vue 框架做单页面应用时,我们时常会遇到传值,组件公用状态的问题.(子父间传值文章传送门) ,如果是简单的应用,兄弟组件之间通信还能使用 eventBus 来作 ...
- 使用Axis2创建一个简单的WebService服务
使用过Java进行过WebService开发都会听过或者接触过Apache Axis2,Axis2框架是应用最广泛的WebService框架之一了. 这里使用Axis2来开发和部署一个最简单的WebS ...
- 方便快捷的求导求积分解方程在线工具sage介绍
有时候我们需要进行一些复杂的数学计算,比如求导, 求积分,解方程,还是用abcd字母代表变量的方程等,这就需要进行复杂的数学运算还需要具备良好的数学基础.不过现在有一个非常方便的在线工具,只需要几 ...