C#学习之委托和事件
C#学习中,关于委托和事件的一些见解:
一.C语言中的函数指针
想要理解什么是委托,就要先理解函数指针的概念。所谓函数指针,就是指向函数的指针(等于没说-.-)。比如我定义了两个函数square和cube分别用于计算一个数的平方和立方,我再定义函数指针calcu,然后我让calcu指向square,那么调用calcu时就相当于调用了square函数(注意,此处函数指针接受的参数类型及个数要与函数一致)。很好理解吧?不多说,上代码。
1 #include <stdio.h>
2
3 void square(int x) { printf("square of %d is %d\n",x,x*x); }
4 void cube(int x) { printf("cube of %d is %d\n",x,x*x*x); }
5
6 int main()
7 {
8 void (*calcu)(int x);
9 calcu=square;
10 calcu(2);
11
12 return 0;
13 }
二.C#中委托的实质
委托又名委托类型,为什么C#弄出这个东西?因为C#是一门比较安全的语言,不允许操作指针,于是我们不能定义函数指针。但想要达到相同的效果,于是定义了委托类型。所谓委托类型,其本质就是C中的指针类型。于是代码变成了这样:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Delegate
8 {
9 class Program
10 {
11 static void square(int x) { Console.WriteLine("square of {0} is {1}", x, x * x); }
12 static void cube(int x) { Console.WriteLine("cube of {0} is {1}", x, x * x * x); }
13
14 delegate void math(int x); //定义委托类型
15
16 static void Main(string[] args)
17 {
18 math calcu;
19 calcu += square;
20 calcu(2);
21 Console.ReadKey();
22 }
23 }
24 }
可以看出,定义委托类型math实际上就相当于定义了void*类型。而委托类型实例化得到的calcu实际上就是函数指针。(说句题外话:定义函数(方法)时要加上static是因为调用函数时并未实例化,只有静态方法能够直接通过类调用)。
三.委托的使用方法
我们在上述代码19行后面加上一行代码 calcu+=cube; 运行会发现,square和cube均被调用。可以看出,符号 += 表示绑定方法到委托变量,同理符号 -= 表示取消绑定。可以理解为calcu是void **类型,即它指向了一个数组,数组中的每一项都是函数指针类型,每次调用calcu时,遍历此数组,即依次调用每个绑定的方法。
四.封装与事件的引入
下面我们要用面向对象的思想将上述代码进行封装,使其变清晰。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Delegate
8 {
9 public delegate void math(int x);
10 public class Calcu
11 {
12 public math calcu;
13 }
14
15 class Program
16 {
17 static void square(int x) { Console.WriteLine("square of {0} is {1}", x, x * x); }
18 static void cube(int x) { Console.WriteLine("cube of {0} is {1}", x, x * x * x); }
19
20 static void Main(string[] args)
21 {
22 Calcu c = new Calcu();
23 c.calcu += square;
24 c.calcu += cube;
25 c.calcu(2);
26 Console.ReadKey();
27 }
28 }
29 }
由于委托变量是public的,封装的程度很低,在外部可以任意修改。为了改进这个问题,C#引入了事件。
所谓事件,实际上还是委托的实例化,只是其内部多了一些定义,多了一些限制。其一,事件实际上声明了一个private类型的委托变量,因此在类外无法直接调用。
于是我们将上述代码的第12行改成这样:
public event math calcu;
运行之后25行报错了,因为calcu是private的,不能直接调用。但23,24行并没有报错。那么问题来了,为什么我们可以用+=来给calcu绑定方法呢?
因为其二,事件还帮我们干了一件事情,就是定义了绑定方法和取消绑定方法的函数,它们是public的,并且将运算符+=,-=重载,和这两个函数对应。
好了,现在我们要写一个接口函数来完成计算:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Delegate
8 {
9 public delegate void math(int x);
10 public class Calcu
11 {
12 public event math calcu;
13 public void calculate(int x)
14 {
15 calcu(x);
16 }
17 }
18
19 class Program
20 {
21 static void square(int x) { Console.WriteLine("square of {0} is {1}", x, x * x); }
22 static void cube(int x) { Console.WriteLine("cube of {0} is {1}", x, x * x * x); }
23
24 static void Main(string[] args)
25 {
26 Calcu c = new Calcu();
27 c.calcu += square;
28 c.calcu += cube;
29 c.calculate(2);
30 Console.ReadKey();
31 }
32 }
33 }
至此,基本概念已经清晰。
想来,使用事件会让人不得不将对象封装起来,这应该就是面向对象思想的体现吧。
(转载他人文章,http://www.open-open.com/lib/view/open1455424278761.html)
C#学习之委托和事件的更多相关文章
- C#学习之委托与事件
委托 语法: public delegate void MyDelegate(); 使用: 1.定义委托----public delegate void MyDelegate(); 2.注册委 ...
- .net学习之委托和事件
1.什么是委托通俗的说:委托就是一个能够存储符合某种格式(方法签名)的方法的指针的容器上传图片: 2.委托语法准备一个方法:string Hello(string userName){} string ...
- .NET委托和事件
.net学习之委托和事件 1.什么是委托 通俗的说:委托就是一个能够存储符合某种格式(方法签名)的方法的指针的容器 上传图片: 2.委托语法 准备一个方法:string Hello(string ...
- C#学习之初步理解委托、事件、匿名方法和Lambda
最经在学习LinqtoSql,然后扯到Lambda表达式,然后扯到匿名方法,然后扯到委托,最后扯到事件处理...后来发现对委托这个概念和事件处理这个过程理解得不是很清晰,遂得一下学习笔记.那里说得不对 ...
- C#学习(一):委托和事件
预备知识 在学习委托和事件之前,我们需要知道的是,很多程序都有一个共同的需求,即当一个特定的程序事件发生时,程序的其他部分可以得到该事件已经发生的通知. 而发布者/订阅者模式可以满足这种需求.简单来说 ...
- C#委托与事件学习笔记
委托事件学习笔记 本文是学习委托和事件的笔记,水平有限,如有错漏之处,还望大神不吝赐教. 什么是委托?从字面意思来解释,就是把一个动作交给别人去执行.在实际开发中最常用的就是使一个方法可以当做一个参数 ...
- C#委托,事件最初浅的和最易看懂的学习笔记
对于委托和事件,看了不少博文,当时好像都理解了,过了一段时间,又忘记的差不多了.每每如此,感觉自己很笨,记性差,其实是没有深入理解透切,没有按照自己的语言表达出来,当然容易忘记.今天又花了一些时间,好 ...
- C#高级编程 (第六版) 学习 第七章:委托和事件
第七章 委托和事件 回调(callback)函数是Windows编程的一个重要方面,实际上是方法调用的指针,也称为函数指针. .Net以委托的形式实现了函数指针的概念,.Net的委托是类型安全的. 委 ...
- c#学习笔记03——委托和事件
委托:一种引用类型,这种类型可以用来定义方法签名,从而使用委托实现将方法作为参数传递给其他方法.类似于C++中的函数之争,使用委托使程序员可以将方法引用封装在委托对象内. 定义和声明委托: deleg ...
随机推荐
- swagger搭建(基于springBoot)详解
前后端分离后,api接口文档的维护就成了一个让人头疼的问题,api接口更新慢,或因开发工作量大,没时间整理文档,导致前后端分离后前端同学和后端同 学都纠结于文档的问题.而swagger的出现,不亚于一 ...
- MySQL5.7多主一从(多源复制)同步配置
MySQL5.7多主一从(多源复制)同步配置(抄袭) 原文地址:https://my.oschina.net/u/2399373/blog/2878650 多主一从,也称为多源复制,数据流向: 主库1 ...
- java的impl
java impl 是一个资源包,用来存放java文件的. 在Java开发中,通常将后台分成几层,常见的是三层mvc:model.view.controller,模型视图控制层三层,而impl通常处于 ...
- N1, T1刷机记录
硬件配置 N1和T1使用的是晶晨Amlogic方案的芯片, 配置明细分别如下, 都是现在盒子的主流配置 N1CPU: Amlogic S905, ARM Cortex-A53 四核 up to 2.0 ...
- 一张图作为Python入门(图片来自网络)
- spring-mybatis-data-common程序级分表操作实例
spring-mybatis-data-common-2.0新增分表机制,在1.0基础上做了部分调整. 基于机架展示分库应用数据库分表实力创建 create table tb_example_1( i ...
- OpenCV 学习笔记 04 深度估计与分割——GrabCut算法与分水岭算法
1 使用普通摄像头进行深度估计 1.1 深度估计原理 这里会用到几何学中的极几何(Epipolar Geometry),它属于立体视觉(stereo vision)几何学,立体视觉是计算机视觉的一个分 ...
- SNF开发平台WinForm-Grid表格控件大全
我们在开发系统时,会有很多种控件进行展示,甚至有一些为了方便的一些特殊需求. 那么下面就介绍一些我们在表格控件里常用的方便的控件: 1.Grid表格查询条 Grid表格下拉 3.Grid表格弹框选 ...
- JAVA(二)异常/包及访问权限/多线程/泛型
成鹏致远 | lcw.cnblog.com |2014-01-28 异常 1.异常的基本概念 异常是导致程序中断运行的一种指令流 基本的异常处理格式:try...catch,try中捕获异常,出现异常 ...
- FROM USE CASES TO TEST CASES
FROM USE CASES TO TEST CASES -Test note of “Essential Software Test Design” 2015-08-31 Content: 12.1 ...