C#的委托与C++的函数指针类似,但委托是类型安全的,意味着指针始终会指向有效的函数。委托的使用主要有两种:回调和事件。

一 将委托作为回调函数

在需要给一个函数传递一个函数指针,随后通过函数指针调用函数时,就可以使用回调函数的方式。回调函数经常用于异步编程,如果被调用的方法执行起来比较费时,就可以把这个方法放在单独在线程执行,同时将函数指针交给回调函数,线程结束时再调用回调函数。这样调用者就不必因等待执行起来费时的方法而被阻塞了。

a) 举例,有一个数据库管理类DBManager,这个类追踪所有激活的数据库连接DBConnection,并通过EnumConnections()方法可以遍历输出这些连接。假设DBManager运行在远程服务器上,那么最好异步执行EnumConnections方法,并使用回调函数接收结果。

DBConnection类如下:

DBManager类如下:

这里声明了委托EnumConnectionsCallback,方法签名为无返回值、有一个DBConnection参数,在调用EnumConnections方法时,传递EnumConnectionsCallback类型的函数指针。

然后调用代码写法如下:

函数指针指向了ActiveConnectionsCallBack方法,这个方法与定义的委托具有相同的签名。

b) 每次调用EnumConnections方法时都需要实例化EnumConnectionsCallback,这样使用起来很不方便,那么就可以将myCallBack修饰为静态的,方便每次直接使用。

c) 关于回调函数的命名规范,通用的做法是以Callback结尾,但有时委托本身往往也经常以Callback结尾,这时需要注意区分二者,因为回调函数属于方法,而委托属于类,如果二者混淆,会导致编译错误。

d) 委托的初始化往往比较耗费时间和资源,而且并不能保证初始化后一定会被用到,于是可以延迟其初始化,只有在开始使用前,才进行初始化,使用只读属性可以实现这个思路

e) 如果需要同时使用多个委托,该如何做呢,比如有一个库存管理类一旦商品数量低于警戒值,一方面会记录日志,另一方面会发邮件给相关人员。主要改变的地方在初始化委托,将两个委托加起来赋值给callback。

而且两个回调执行的顺序是按照相加的顺序的。还可以使用减号解除某个回调。

f) Windows系统有许多场合用到了事件,如消息队列、用户交互等。C#中的事件遵循发布-订阅(观察者)模式,一个消息源可以被多个对象订阅。事件是特殊的委托,这种委托必须有两个参数,第一个参数为发布者或者说事件的触发者,第二个参数为派生自EventArgs的对象。

学习资料:Inside C# by Tom Archer

《Inside C#》笔记(十二) 委托与事件的更多相关文章

  1. 《C++游戏开发》笔记十二 战争迷雾:初步实现

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9475979 作者:七十一雾央 新浪微博:http:/ ...

  2. python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  3. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  4. DirectX11笔记(十二)--Direct3D渲染8--EFFECTS

    原文:DirectX11笔记(十二)--Direct3D渲染8--EFFECTS 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010333737 ...

  5. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  6. .NET面试题系列(十)委托与事件

    委托 有了委托的存在,使得方法可以作为参数传递给另一个方法. int Max(int x,int y) { return x>y?x:y; } int Min(int x,int y) { re ...

  7. 《深入理解Java虚拟机》读书笔记十二

    第十二章  Java内存模型与线程 1.硬件效率与一致性 由于计算机的存储设备与处理器的运算速度有几个数量级的差距,所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(Cac ...

  8. Unity3D笔记十六 输入输出-键盘事件、鼠标事件

    输入与控制操作Unity为开发者提供了Input类库,其中包括键盘事件.鼠标事件和触摸事件等一切跨平台所需要的控制事件. 一.键盘事件 1.按下事件 Input.GetKeyDown():如果按键被按 ...

  9. (C/C++学习笔记) 十二. 指针

    十二. 指针 ● 基本概念 位系统下为4字节(8位十六进制数),在64位系统下为8字节(16位十六进制数) 进制表示的, 内存地址不占用内存空间 指针本身是一种数据类型, 它可以指向int, char ...

随机推荐

  1. [源码]K8 Cscan模块 C#获取内网主机IP/机器名/Banner/网页标题源码

    [原创]K8 Cscan 大型内网渗透自定义扫描器 https://www.cnblogs.com/k8gege/p/10519321.html Cscan简介:何为自定义扫描器?其实也是插件化,但C ...

  2. shell之实战应用一(查找xml文档中的关键字段)

      前几天同事问我一个问题,说如下的文档中,如何把name后面的字段(红色框中的字段)单独打印出来?

  3. java中Memcache的使用

    java中Memcache的使用 一.什么是Memcached? Memcached是danga.com开发的分布式内存对象缓存系统,所谓分布式,意味着它不是本地的,而是基于网络连接完成服务.Memc ...

  4. Eclipse常用注释设置

    菜单:Window→Preferences→Java→Code Style→Code Template Files /** * @Title: ${file_name} * @Package ${pa ...

  5. Filebeat的Registry文件解读

    你可能没有注意但很重要的filebeat小知识 Registry文件 Filebeat会将自己处理日志文件的进度信息写入到registry文件中,以保证filebeat在重启之后能够接着处理未处理过的 ...

  6. 函数调用的区别:_cdecl以及_stdcall

    一.概念1)_stdcall调用   _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,由调用者完成压栈操作,被调函数自身在返回前清空堆栈.   WIN32 Api都采用_ ...

  7. 获取访问者的IP地址

    function getIp() { $realip = NULL; if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ipArray = explode( ...

  8. Tomcat启动时项目重复加载的问题

    最近在项目开发测试的时候,发现Tomcat启动时项目重复加载,导致资源初始化两次的问题  导致该问题的原因: 如下图:在Eclipse中将Server Locations设置为“Use Tomcat ...

  9. Apache RocketMQ在linux上的常用命令

    Apache RocketMQ在linux上的常用命令 进入maven安装后的rocketmq的bin目录  1.启动Name Server  2.启动Broker 3.关闭Name Server 4 ...

  10. nginx作为web服务以及nginx.conf详解

    Nginx系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html 1.nginx简介 nginx是一个优秀的web服务程序.反向代理程序.它采用非 ...