C#编程语言之委托与事件(二)—— C#事件
前面已经大致讲述了C#委托的一些基础知识点,本文接下来的内容是C#中的事件(Event),在此我提个建议,如果是刚接触C#的委托类型的朋友可以先看到这里,等熟悉了委托的使用之后(大约1-2天)再来了解C#中事件的使用,以免看了以下内容发生思维紊乱的现象。之所以这么说并没有些许自大之意,而相反的是恰恰是认为自己的文章写得结构混乱,不足以明理,如果同时看了委托(delegate)和事件(event)容易知识点混淆,所以只是稍作提醒。
好了,废话不多说,现在进入正题:
事件是什么?C#事件是一种具有特殊签名的委托,且在声明事件类型的时候用event关键字修饰。
说到事件,大家第一个想到的一般都是按钮点击事件,既然说到按钮点击事件,下面就着按钮事件作为例子说开去。
首先,在Winform界面拖拽一个按钮,双击按钮,代码会自动定位到按钮点击函数,右击点击事件的函数名,查找所有引用,可以看到总共包括以下两处引用:
private void button1_Click(object sender, EventArgs e) {}
this.button1.Click += new System.EventHandler(this.button1_Click);
在上面为什么我要特别提到定位到第一个语句是一个函数,而不是事件,因为真正的时间是那个 button1.Click 而不是那个 button1_Click ,因为经常听到有人提到说“双击按钮定位到按钮点击事件”,个人感觉这个说法对事件的概念有失偏颇,顺带地提一提。
在此可以看到函数的参数列表(object sender, EventArgs e),这个参数列表必须是确定的,一个表示点击事件的执行者,一个表示事件参数类,不局限于object和EventArgs,但必须是这个两个类的子类或本身。
下面看一下创建一个事件的步骤:1
(1)、定义delegate对象类型,它有两个参数,第一个参数是事件发送者对象,第二个参数是事件参数类对象
(2)、定义事件参数类,此类应当从System.EventArgs类派生
(3)、定义事件处理方法,此方法符合步骤(1)定义的委托签名
(4)、用event关键字定义事件对象,它同时也是一个delegate对象
(5)、用+=操作符添加事件到事件队列当中,-=操作符把事件从事件队列中删除
(6)、在需要触发事件的地方调用delegate的方式写事件触发方法。一般来说,此方法应为protected访问限制,既不能以public方式调用,但可以被子类继承。
下面我们通过模拟一个Button点击事件来深入了解:
using System;
namespace ConsoleApplication {
//(1)定义一个delegate对象类型
delegate void myEventHandle(object sender, EventArgs e);
class MyEventArg : EventArgs {
//(2)定义事件类,应派生于EventArgs类
public string EventArgsName() {
return "[MyEventArgsName]";
}
}
class _Button {
//(4)定义事件对象,注意关键字和类型
public event myEventHandle Click;
protected void OnUtilEvent(MyEventArg e) {
if(null != Click) {
Click(this, e);
}
}
public void RaiseEvent() {
MyEventArg e = new MyEventArg();
OnUtilEvent(e);
}
public string ButtonName() {
return "[myButtonName]";
}
}
class EventTest {
//(3)定义事件处理方法,保证函数列表和返回值的有效性
static void _Button_Click(object sender, EventArgs e) {
Console.WriteLine("\nYou have clicked the button");
Console.WriteLine("The eventObject is :\t"+(sender as _Button).ButtonName());
Console.WriteLine("The eventArgs is:\t"+(e as MyEventArg).EventArgsName());
}
static void Main() {
_Button _button = new _Button();
//(5)用操作符把事件添加到事件队列当中
_button.Click += new myEventHandle(_Button_Click);
Console.Write("Do you want to click the button(Y/N)");
if (Console.ReadKey().KeyChar == 'Y')
_button.RaiseEvent();
else
Console.WriteLine("The event does not raise");
}
}
}
其中我已经把创建步骤写成注释表明在代码中了,模拟鼠标点击事件我们修改为按下“Y”触发,当看到 _button.Click += new myEventHandle(_Button_Click); 有没有恍然大悟的感觉。其实原理并不难,多练习几次条理就清晰。书读百遍,其义自现,说的亦是如此。
使用某IDE编写以上例子的时候可能在 if(null != Click){ Click(this,e); } 这段语句时会报一个[NOTICE],提示该表示方法可以简单化,可以改成 Click?.Invoke(this, e); 注意这不是错误,如此表示只是为了降低理解难度,其实两个语句的作用是一样的,判断Click对象是否为null,然后执行该事件。
事件发布器:
通过一个例子来直接了解事件发布
using System;
namespace ConsoleApplication {
public delegate void myEventHandle(object sender,FoodEventArg e);
public class FoodEventArg : EventArgs {
private string food;
public FoodEventArg(string food) {
this.food = food;
}
public string getFood() {
return food;
}
}
class Person {
private string name;
public Person(string name) {
this.name = name;
}
public void FoodRecive(object sender,FoodEventArg e) {
Console.WriteLine("{0} receives {1}",name,e.getFood());
}
}
class Dealer {
public event myEventHandle FoodInfo;
public void Receive(string food) {
Console.WriteLine("Dealer: food->{0}",food);
RaiseEvent(food);
}
protected void RaiseEvent(string food) {
FoodInfo?.Invoke(this, new FoodEventArg(food));
}
}
class EventTest {
static void Main() {
Dealer _dealer = new Dealer();
Person _personA = new Person("Evan");
Person _personB = new Person("Cathy");
_dealer.FoodInfo += _personA.FoodRecive;
_dealer.Receive("Rice");
_dealer.FoodInfo += _personB.FoodRecive;
_dealer.Receive("Potato");
_dealer.FoodInfo -= _personA.FoodRecive;
_dealer.Receive("Cucumber");
}
}
}
使用Dealer的FoodInfo事件,通过“+=”来注册一个订阅(实质上就是把一个事件添加到事件队列当中),通过“-=”来取消一个订阅。
例子中食物(Food)的接收一个事件参数,当一个食物被接收时,查看有多少用户订阅该事件可以接收到该食物,一开始只有Even订阅了事件,所以Even接收到了Rice,然后Cathy注册了订阅,所以Even和Cathy(队列结构)依次接收到了Potato,随后Even取消了订阅,所以后来的Cucumber只有当前注册订阅用户Cathy能够接收。
懒得手写运行结果,以下贴出运行结果图:

通过这个例子能够比较清楚地明白C#事件当中 事件执行 者和 事件参数 的作用,C#事件是一种新的类型处理方式,同时更是一种设计模式。
声明:以上 C#编程语言之委托与事件(一)和 C#编程语言之委托与事件(二)均由本人原创编写,文中的每一处代码均经过本人亲自测试能够按照文中所述的结果呈现,如果问题,请及时告知。
文章引用:
1、http://www.cnblogs.com/xlx0210/archive/2010/08/08/1794959.html
尊重知识产权,争取共同进步!
C#编程语言之委托与事件(二)—— C#事件的更多相关文章
- C#特性知识图谱-二、事件
C#特性知识图谱-二.事件 二.事件 在事件驱动的软件系统中,符合某种预设条件的情形出现是,一个事件就会被触发. 2.1 事件三要素 事件源:激发事件的对象 事件信息:事件本身说携带的信息 事件响应者 ...
- javaScript事件(二)事件处理程序
一.事件 二.事件流 以上内容见:javaScript事件(一)事件流 三.事件处理程序 前面提到,事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字.响应 ...
- 解密jQuery事件核心 - 委托设计(二)
第一篇 http://www.cnblogs.com/aaronjs/p/3444874.html 从上章就能得出几个信息: 事件信息都存储在数据缓存中 对于没有特殊事件特有监听方法和普通事件都用ad ...
- Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制
一.事件的捕获与冒泡 由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和冒泡阶段,会依次检查途径的每个节点,如果该节点注册了相应的监听函数,则执行监 ...
- .NET Core 跨平台物联网开发:设置委托事件(二)
系列教程目录 (一) 连接阿里云IOT (二) 设置委托事件 (三) 上报属性 (四) SDK文档 属性.方法.委托.类 http://pan.whuanle.cn/index.php?dir=up ...
- C++模拟C#事件委托机制(二)
原文 来自于http://www.cnblogs.com/netssfy/archive/2010/02/02/1662056.html 为了解决非法地址访问的冲突,首先需要知道发生该错误的原因是什么 ...
- HTML 事件(二) 事件的注册与注销
本篇主要介绍HTML元素事件的注册.注销的方式. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流.事件委托 4. ...
- HTML 事件(三) 事件流与事件委托
本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...
- js事件捕获,事件冒泡,事件委托以及DOM事件流
一:DOM事件流: 事件流是从页面接收事件的顺序,DOM2级事件规定事件流包括三个阶段: ①事件捕获阶段:用意在于事件达到目标之前捕获它,在事件捕获阶段事件流模型:document→html→body ...
随机推荐
- (python)剑指Offer(第二版)面试题14:剪绳子
题目 给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],…,k[m].请问k[0]k[1]…*k[m]可能的最大乘积是多少 ...
- CSS3 column属性
css3 column属性的应用 1.案例源码 <!DOCTYPE html><html lang="en"><head> <meta c ...
- 一个小的tab切换插件
1//使用 var t1=new Tab({ etype:'onmou',//默认点击触发,如果事件写错了,当作单击 autoplay:2000,//有时间值(按照事件自动播放)和false(不自动播 ...
- CF922 CodeForces Round #461(Div.2)
CF922 CodeForces Round #461(Div.2) 这场比赛很晚呀 果断滚去睡了 现在来做一下 A CF922 A 翻译: 一开始有一个初始版本的玩具 每次有两种操作: 放一个初始版 ...
- 【Luogu3121】审查(AC自动机)
题面 Description 农夫约翰为他的奶牛们购买了一份名字叫Good Hooveskeeping的定期杂志,因此奶牛们在挤奶期间就有了大量的阅读素材.遗憾的是在最新的一期上,有一篇有点儿不适当的 ...
- Invalid bound statement (not found)解决方法
项目背景:SSM框架,MySQL数据库 报错情况: 错误原因:Mybatis的xml文件中,namespace路径错误!!引入的不是对应的Dao接口!!! Dao接口和对应的xml文件 必须一一对应! ...
- 关于input 的选中,自定义input[type="checkbox"]样式
1.css 呈现 选中后 的input的样式可以用 /*背景图*/ background:url('../pc/images/archives/icon_choosed.png') no ...
- 如何将VMware虚拟机迁移到AWS
在工作中,我们一直在努力将我们的一些VMware工作负载转移到AWS,并且我的任务是将几个VMware虚拟机迁移到AWS,作为暂时的概念验证. 在本文中,我将展示如何设置AWS连接器并使用AWS服务器 ...
- java ---日期的格式化
import java.util.Date; import java.util.Scanner; import java.text.SimpleDateFormat; import java.util ...
- GitHub起步---创建第一个项目
---恢复内容开始--- 刚起步学习GitHub,边学边说! {参考教程:http://blog.csdn.net/steven6977/article/details/10567719}这里描述的很 ...