在C#中我们经常会碰到事件,尤其是在WPF或者WinForm中,窗体加载、或者点击一个按钮,都会触发事件。实际上,事件是对委托的封装。如果不进行封装,让委托暴露给调用者,调用者就可以把委托变量重新引用到新的委托对象,也就删除了当前要调用的方法列表;更糟糕的是,公共的委托成员打破了封装不仅导致代码难以维护和调试,而且会导致应用程序有安全风险。下面分别说明。

1、委托

委托可以理解为一种协议。委托,是什么意思呢?举个例子,你碰到一件事,你需要让别人来帮你做(可能你还有别的事情要做),这就是委托,把你现在不能做的事让别人去做。为什么说委托就像一个协议呢,因为你不想把事情搞砸了,所以你“委托”的这个人做的这件事,你需要给他定一个标准。在C#中就是给所委托的对象定义好签名,参数有几个,分别是什么类型,委托方法需要反馈给你什么东西(或者不反馈)。从这种意义上理解,委托就像是一种协议。下面是例子。

         public delegate int MyDelegate(int x, int y);
class Delegate_Demo
{
static void Main(string[] args)
{
//实例化被委托者
Helper helper = new Helper();
//创建委托对象
MyDelegate myDele = new MyDelegate(helper.Add);
int sum = myDele(, );
Console.WriteLine(sum);
} }
class Helper
{
public Helper() { } public int Add(int num1, int num2)
{
return num1 + num2;
}
}

上述例子中public delegate int MyDelegate(int x, int y);声明了一个委托,告诉被委托者这件事你要这么干,我给你两个整数,你计算他们的和,怎么计算我不管,计算完之后你把和给我。

2、事件

在某件事情发生时,一个对象可以通过事件通知另一个对象。比如,前台界面一个求和按钮被点击了,他通知你,可以把a和b这两个数相加了。这就是一个事件。可以看出事件是在一个时间节点去触发另外一件事情,而另外一件事情怎么去做,他不会关心。就事件来说,关键点就是什么时候,让谁去做。

在编译器处理event关键字时,会自动提供注册和注销方法以及任何必要的委托类型成员变量(私有的),因此不能从触发事件的对象去调用它们,event关键字就像一个语法糖,节省了我们打字的时间。

定义一个事件有两步,首先定义一个委托,它包括了这件事的“协议”和委托方法(由谁去做);其次,用event关键字和相关委托声明这个事件。事件像是一个接口,封装了委托所定的“协议”。由于委托已经定义了协议,剩下的就是按这个协议去办事,至于怎么做它并不关心。下面是一个例子。

         public delegate int MyDelegate(int x, int y);
class Delegate_Demo
{
//声明事件
static event MyDelegate myEvent;
static void Main(string[] args)
{
//交代事件
myEvent += new Helper().Add;
int sum = myEvent(, );
Console.WriteLine(sum);
} }
class Helper
{
public Helper() { } public int Add(int num1, int num2)
{
return num1 + num2;
}
}

从上面可以看出,调用者无法访问委托对象。

3、回调函数

回调函数就是把一个方法的传给另外一个方法去执行。回调函数只是一个功能片段,由用户按照回调函数的调用约定来实现的一个函数。先看一个例子。

         public delegate int MyDelegate(int x, int y);
class Delegate_Demo
{
//声明事件
static event MyDelegate myEvent;
static void Main(string[] args)
{ int sum = MyAdd(, , new Helper().Add);
Console.WriteLine(sum);
}
private static int MyAdd(int a, int b, MyDelegate myDele)
{
return myDele(a, b);
} }
class Helper
{
public Helper() { } public int Add(int num1, int num2)
{
return num1 + num2;
}
}

可以看出,可以把任意一个符合这个委托的方法传递进去,意思就是说这部分代码是可变的。而设计上有一个抽离出可变部分代码的原则,这种用法无疑可以用到那种场合了。

C#中委托、事件和回调函数的理解的更多相关文章

  1. 关于as中的事件与回调函数

    对于Observer模式, 在as中object(被观察者)既可以用事件(event),也可以用回调函数(caller)来通知观察者(observer).那在实际的开发中到底应该选择用event还是用 ...

  2. C# (事件触发)回调函数,完美处理各类疑难杂症!

    每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客! 废话说多了...... 嘿嘿:本篇标题为:C#  (事件触发)回调函数,完美处理各类疑难杂症.个人理解如下:事件触发也就是触 ...

  3. 基于Lwip协议栈中独立模式下回调函数的使用

    一.使用Lwip协议独立模式开发 最近在STM32F4上边移植了Lwip,Lwip是一个小型开源的TCP/IP协议栈,有无操作系统的支持都可以运行.我当前只测试了TCP Server功能,然后对TCP ...

  4. js中的回调函数的理解和使用方法

    js中的回调函数的理解和使用方法 一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为 ...

  5. Unity C# 调用 C++ DLL 并在 DLL 中调用 C# 的回调函数

    Unity C# 调用 C++ DLL 并在 DLL 中调用 C# 的回调函数~~~    呵呵... 看着有点晕.. 再解释一下就是 在Unity中 使用 C# 调用 C++ 写的 DLL, 但是在 ...

  6. python中进程池和回调函数

    一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...

  7. JavaScript callback function 回调函数的理解

    来源于:http://mao.li/javascript/javascript-callback-function/ 看到segmentfault上的这个问题 JavaScript 回调函数怎么理解, ...

  8. 回调函数透彻理解Java

    http://blog.csdn.net/allen_zhao_2012/article/details/8056665 回调函数透彻理解Java 标签: classjavastringinterfa ...

  9. js回调函数(callback)理解

    Mark! js学习 不喜欢js,但是喜欢jquery,不解释. 自学jquery的时候,看到一英文词(Callback),顿时背部隐隐冒冷汗.迅速google之,发现原来中文翻译成回调.也就是回调函 ...

随机推荐

  1. 两种解决IE6不支持固定定位的方法

    有两种让IE6支持position:fixed1.用CSS执行表达式 *{margin:0;padding:0;} * html,* html body{ background-image:url(a ...

  2. .net部署时常见问题

    站点提示“不允许的父路径”怎么办 error: 40 - Could not open a connection to SQL Server解决办法 无法识别的属性“targetFramework”. ...

  3. 微软BI 之SSRS 系列 - 使用 LookupSet 和 Adjacent Group 等高级技巧在报表中跨 Dataset 分组查询

    SSRS 报表中有一些高级的技巧,平常很少用到,下面我通过这个案例来展现一下如何在实际开发中使用它们,并且如何解决一些实际的需求. 这张报表分别统计了不同的 Product 产品在不同的月份的 Ord ...

  4. Mybatis 自动生成代码,数据库postgresql

    最近做了一个项目,使用Mybatis自动生成代码,下面做一下总结,被以后参考: 一.提前准备: 1.工具类:mybatis-generator-core-1.3.2.jar 2.postgresql驱 ...

  5. eclipse 远程调试程序

    最近遇到一个非常恶心的问题,本地调试没有问题,到了线上就复发,逼于无奈只能使用eclipse远程调试,下面把步骤记录一下: 1.修改服务器的启动脚本,添加如下内容: export JPDA_ADDRE ...

  6. Vue为什么没有templateUrl

    Why Vue.js doesn't support templateURL Vue.js为什么不支持templateUrl模式 原因 templateUrl使用ajax的方式在运行时加载templa ...

  7. 算法笔记_214:第六届蓝桥杯软件类校赛真题(Java语言A组)

    目录 1 题目一 2 题目二 3 题目三 4 题目四 5 题目五 6 题目六 7 题目七 前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 题目一 一个串的子串是指该串的一个连续的局部.如果不要求连续 ...

  8. 【DB2】查看表空间对应的物理文件地址

    使用的命令: db2 list tablespaces show detail db2 list tablespace containers for [Tablespace ID] [show det ...

  9. LS下怎样最大限度的提高Domino下Web应用的速度

    1.用For 循环代替Do 循环,因为Do循环会反复的计算条件! 2.在数族元素中循环式用Forall代替for.一元数组会快75%,二元会快50%左右. 3.简化If里的条件,如:if a=x an ...

  10. DHCP 服务测试

    DHCP三个端口: 服务端:UDP 67 客户端:UDP 68 DHCPv6 客户端:UDP 546,这是需要特别开启的 DHCP failover 服务,用来做双机热备的. 实验一.DHCP服务器基 ...