委托

委托是一个非常不错的设计,允许我们把方法做为参数传递,实现了开放閉放原则。在方法中我们只要有一个委托占位,调用者就可以传入符合签名的方法来做不同的操作,这也面向对象开发中多态的魅力。

但是在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 委托的更多相关文章

  1. 委托,匿名函数和lambda表达式

    很早之前就接触到了委托,但是一直对他用的不是太多,主要是本人是菜鸟,能写的比较高级的代码确实不多,但是最近在看MSDN微软的类库的时候,发现了微软的类库好多都用到了委托,于是决定好好的研究研究,加深一 ...

  2. C#—委托分析

    1.简单委托示例 using System; using System.Collections.Generic; using System.Linq; using System.Text; names ...

  3. C# 语言规范_版本5.0 (第1章 介绍)

    1. 介绍 C#(读作“See Sharp”)是一种简洁.现代.面向对象且类型安全的编程语言.C# 起源于 C 语言家族,因此,对于 C.C++ 和 Java 程序员,可以很快熟悉这种新的语言.C# ...

  4. C#6.0语言规范(一) 介绍

    C#(发音为“See Sharp”)是一种简单,现代,面向对象,类型安全的编程语言.C#源于C语言系列,对C,C ++和Java程序员来说很熟悉.EC#International将EC#标准化为ECM ...

  5. C# Language Specification 5.0 (翻译)第一章 引言

    C#(念作 See Sharp)是一种简单.现代.面向对象并且类型安全的编程语言.C# 源于 C 语言家族,因此 C.C++ 和 Java 工程师们能迅速上手.ECMA 国际[1](ECMA Inte ...

  6. C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数

    一.隐式类型var 从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,编译器自动推断类型. 1.var类型的局部变量必须赋予初始值,包括匿名 ...

  7. C#指南,重温基础,展望远方!(11)C#委托

    委托类型表示对具有特定参数列表和返回类型的方法的引用. 通过委托,可以将方法视为可分配给变量并可作为参数传递的实体. 委托类似于其他一些语言中的函数指针概念,但与函数指针不同的是,委托不仅面向对象,还 ...

  8. C#中委托的发展与匿名函数

    匿名函数(C# 编程指南) 匿名函数是一个“内联”语句或表达式,可在需要委托类型的任何地方使用. 可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数. 共有两种匿名函数 ...

  9. jquery2.0.3 全部源码

    /*! * Includes Sizzle.js 选择器,独立的库 * http://sizzlejs.com/ */ (function( window, undefined ) { //" ...

随机推荐

  1. 如何让Qt程序在运行时获取UAC权限

    在pro文件中加入以下语句: QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'requireAdministrator\' uiAccess=\'false\' ...

  2. Java_重载与重写

    在java中,重载与重写都是多态的体现.重载(Overload)体现的是编译时多态,而重写(Override)体现了运行时多态. 重载(Overload): 定义:在一个类中,同名的方法如果有不同的参 ...

  3. 初识Jmeter

    初识Jmeter 测试计划是根节点,其下可以有多个Thread Group,起始可配setUp Thread Group和tearDown Group.在每个Group下可创建其它节点,模拟各类实际行 ...

  4. vue常用属性

    关键词:filters  | 自定义过滤器 (首字母大写) <p>{{ msg | capitalize }}</p> filters: { capitalize: funct ...

  5. rest_framework之权限源码剖析

    权限问题 1.models.py 2.用户类型: 3.views.py: 假设订单相关业务(只有SVIP用户有权限) 假设用户信息相关业务(只有普通用户.VIP有权限) 4.运行结果: 基本使用 以上 ...

  6. Keepalived+Nginx实现高可用Web负载均衡

    1.安装编译 Nginx 所需的依赖包# yum install gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zli ...

  7. hive的join

    第一:在map端产生join          mapJoin的主要意思就是,当链接的两个表是一个比较小的表和一个特别大的表的时候,我们把比较小的table直接放到内存中去,然后再对比较大的表格进行m ...

  8. NFS 系统搭建 - 成功

    NFS是Network File System的缩写,即文件系统.客户端通过挂载的方式将NFS服务器端共享的数据目录挂载到本地目录下. 工作流程 1.由程序在NFS客户端发起存取文件的请求,客户端本地 ...

  9. BurpSuite 代理设置的小技巧

    原文:https://www.anquanke.com/post/id/85925 作者:三思之旅 预估稿费:300RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿 在We ...

  10. LoadRunner(四)——深度了解LR相关功能

    参考学习感谢:<精通软件性能测试与LoadRunner实战> 相关功能: 1 无工具情况下的性能测试 2性能测试工具LoadRunner的工作原理 3 VuGen应用介绍 4 协议的类型及 ...