本节对事件进行总结。

二、事件:

1、概念:Event:A member that enables an object or class to provide notifications;官方的解释是这样,就是说在C#中,事件是使

对象或者类具备通知能力的成员。比如说手机收到短信提醒我去开会,那么手机就充当了一个具备通知能力的成员。说白了,事件

的作用就是对象和类之间的信息传递的桥梁。

2、原理:源于发生-响应模型:

事件源(event source) + 事件本身(event) => 事件的订阅者(event subscriber) + 事件处理器(event handler)

(另外还有事件的订阅者和事件源之间的订阅关系subscribe relationship)

还是以手机收到短信提醒我去开会为例,事件源:手机吗,事件:收到短信,事件的订阅者:我,事件处理器:去开会,订阅关系:我订阅手机

3、事件的声明:分为详细声明和简略声明:

(1)详细声明:

public delegate void MyDelegateEventHandler();
public class Event
{
private MyDelegateEventHandler myDelegateEventHandler;
public event MyDelegateEventHandler MyDelegate
{
add
{
this.myDelegateEventHandler += value;
}
remove
{
this.myDelegateEventHandler -= value;
}
}
}

(2)简略说明:

public delegate void MyDelegateEventHandler();
public class Event
{
public event MyDelegateEventHandler myDelegate;
}

可以看到,在完整声明中首先添加了一个委托类型的字段,然后暴漏了添加和移除事件处理器的功能,但是我们经常用的是简略声明,因为代码更加简洁,

可以看出事件对外界隐藏了大部分功能,它的本质就是对其中委托字段的一个封装(encapsulation),防止外界偷用滥用委托字段。

那么问题来了:第一个问题:有了委托为什么还会有事件呢,事件内部不就是委托吗,原因是为了防止public型的委托字段在外面被滥用,比如委托可以用invoke调用,

但是事件只能在+=或-=的左侧,这样就增加了整个程序的安全性。

第二个问题:那委托和事件的关系什么样的呢?我们说事件是基于委托的。一方面,事件需要委托来做一个约束,这个约束规定了事件源发送什么要求给事件的订阅者,

事件订阅者的事件处理器必须和这个约束相对应才可以订阅这个事件,另一方面,事件订阅者收到事件以后做出事件处理器,而这个事件处理器必须通过委托才可以做到。

4、简单实例:

Example:做一个窗口,有文本框和按钮,点击按钮文本框显示时间,不用WindowsForms

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; namespace ConsoleApp14
{
class Program
{
public static TextBox textBox;
public static Button button;
static void Main(string[] args)
{
Form form = new Form();
TextBox textBox = new TextBox();
Button button = new Button();
form.Controls.Add(textBox);
form.Controls.Add(button);
textBox.Width = ;
button.Top = ;
button.Click += Button_Click;
form.ShowDialog();
} private static void Button_Click(object sender, EventArgs e)
{
textBox.Text = DateTime.Now.ToString();
}
}
}

这里举的事例就是windowsforms内部的代码,我们说事件本身是不会发生的是由事件源内部的逻辑所触发,在本例中,并不是人按了按钮然后按钮触发了事件,

这其中还有一个小过程,就是当按钮被key down再key up时,向程序内部发送了一系列电讯号,通知电脑,然后再发生事件,

5、声明事件的相关约定:

用于声明事件的委托一般用:事件+EvnetHandler,参数一般有2个,第一个事件源,第二个EventArgs的派生类,用于触发事件的方法名一般为On+方法名,

访问级别Protected。可能有点蒙,举个实例就懂了。

Example:举一个顾客在KFC点餐的例子

namespace ConsoleApp15
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
Waitor waitor = new Waitor();
customer.Order += waitor.Serve;
customer.Eat();
customer.Pay();
}
}
public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);
public class Customer
{
public int Money { get; set; }
public event OrderEventHandler Order;
public void Pay()
{
Console.WriteLine($"OK,{Money} dollars");
}
public void Eat()
{
Console.WriteLine("Let's go to the KFC...");
Console.WriteLine("Stand in front of the waitor...");
Console.WriteLine("A hamburger,Please...");
OnOrder();
}
protected void OnOrder()
{
OrderEventArgs orderEventArgs = new OrderEventArgs();
orderEventArgs.Snack = "Hamburger";
orderEventArgs.Size = "large";
this.Order.Invoke(this, orderEventArgs); }
}
public class OrderEventArgs : EventArgs
{
public string Snack { get; set; }
public string Size { get; set; }
}
class Waitor
{
public void Serve(Customer customer, OrderEventArgs e)
{
Console.WriteLine($"Here is your snack {e.Snack}");
int price = ;
switch (e.Size)
{
case "large":
price *= ;
break;
case "small":
price *= ;
break;
default:
break;
}
customer.Money += price;
}
}
}

按照事件的五个要素,首先需要事件源,做一个Customer类,还需要一个事件订阅者,做一个Waitor类,然后根据订阅关系去写具体的方法,订阅关系customer.Order += waitor.Serve; Customer点餐Waitor服务,waitor类中上餐并算好价格,这个时候需要一个事件处理器OrderEventHandler,这个委托的参数需要一个OrderEventArgs,创建这个类写好属性,在写好委托和事件,然后在Customer类中写点餐事件,点餐事件为Protected的,和public型的委托字段一样防止被外界滥用,提高安全性。

想融会贯通其实也不难,只需要将事件的5个要素每一个列举出来,那么最后事件也就出来了。

至此事件总结完毕,有不明之处还请指教。                2018-08-17   16:43:19

C#委托、事件剖析(下)的更多相关文章

  1. Observer设计模式中-委托事件-应用在消息在窗体上显示

    Observer设计模式:监视者模式.在类中的方法中处理的结果或者消息通过事件委托 的方式发送给主窗体. 因为在其它类中直接访问主窗体类,显示内容是不能直接调用控件赋值的,当然也有别的类似查阅控件名, ...

  2. Asp.net用户控件和委托事件

    在Asp.net系统制作过程中,门户类型的网站,我们可以用DIV+CSS+JS+Ajax全部搞定,但是一旦遇到界面元素比较复杂的时候,还是UserControl比较方便一些,各种封装,各种处理,然后拖 ...

  3. c#委托事件及其讲解

    一定要标明出处,波哥的文章.所有文章都值得一看.这篇是摘抄的大白话之C#事件讲解.委托 http://www.cnblogs.com/wudiwushen/archive/2010/04/20/170 ...

  4. JQuery基础教程:事件(下)

     事件传播     为了说明不可单击的页面元素处理单击事件的能力,例如样式转换器中包含按钮的div元素或者兄弟元素h3,我们来实现一个鼠标指针进入元素和离开元素时的效果,首先需要添加一种翻转状态,表明 ...

  5. c#委托事件入门--第二讲:事件入门

    上文 c#委托事件入门--第一讲:委托入门 中和大家介绍了委托,学习委托必不可少的就要说下事件.以下思明仍然从事件是什么.为什么用事件.怎么实现事件和总结介绍一下事件 1.事件是什么:. 1.1 NE ...

  6. Unity C#笔记 委托&事件

    C#的委托与事件搭配,即是观察者模式的一种实现. 因为观察者模式的原理很易懂,不作多讲,本文纯粹用于记录语法. delegate(委托) //声明没有参数,没有返回值的委托类型XXXX public ...

  7. python 全栈开发,Day55(jQuery的位置信息,JS的事件流的概念(重点),事件对象,jQuery的事件绑定和解绑,事件委托(事件代理))

    一.jQuery的位置信息 jQuery的位置信息跟JS的client系列.offset系列.scroll系列封装好的一些简便api. 一.宽度和高度 获取宽度 .width() 描述:为匹配的元素集 ...

  8. Delegate,Action,Func,匿名方法,匿名委托,事件 (转载)

    Delegate,Action,Func,匿名方法,匿名委托,事件 (转载) 一.委托Delegate 一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本 ...

  9. 理解js事件冒泡事件委托事件捕获

    js事件冒泡 javascript的事件传播过程中,当事件在一个元素上出发之后,事件会逐级传播给先辈元素,直到document为止,有的浏览器可能到window为止,这就是事件冒泡现象. <di ...

随机推荐

  1. Android之ViewPager循环Demo

    ViewPager是谷歌官方提供的兼容低版本安卓设备的软件包,里面包含了只有在安卓3.0以上可以使用的api.Viewpager现在也算是标配了,如果一个App没有用到ViewPager感觉还是比较罕 ...

  2. Android动画-补间(Tween)动画

    Android动画的两种方式,其中帧动画上篇文章已经讲了,这次主要讲解的就是补间动画,补间动画就是动画业务场景中常用的旋转,平移,缩放,和渐变效果,帧动画是通过轮播动画实现动画效果,补间动画通过在两个 ...

  3. docker 基本原理及快速入门

    作者地址:青牛 什么是docker Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目.它基于 Google 公司推出的 Go 语言实现. 项目后来 ...

  4. Oracle Agile PLM Web Services 的实现

    Oracle 的产品Agile PLM内置了许多Web Services,其他系统可以通过Web Servcies实现对Agile PLM系统资源的访问.快速学会使用的方法,是去Oracle的官网下载 ...

  5. socket bind 随机端口

    https://www.cprogramming.com/code_blocks/ 这个地址可以下载c, c++的编译器,在windows下可以用的 IDE. bind到端口0上,系统就会自动分配,但 ...

  6. (LeetCode 160)Intersection of Two Linked Lists

    Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...

  7. uva 696 - How Many Knights

    题目链接:uva 696 - How Many Knights 题目大意:给出一个n * m的网格,计算最多可以放置几个国际象棋中的骑士. 解题思路:分成三类来讨论: 1)min(n, m) == 1 ...

  8. RTT下spi flash+elm fat文件系统移植小记

    背景: MCU:STM32F207 SPI flash: Winbond W25Q16BV OS: RTT V1.1.1 bsp: STM32F20x 1 将spi_core.c,spi_dev.c及 ...

  9. UEFI是什么?与BIOS的区别在哪里?UEFI详解!

    前几天在帮同事小何笔记本电脑安装64位 Windows 7 的时候,遇到一个从来没有碰到过的问题,使用光盘安装时,提示:Windows无法安装到这个磁盘.选中的磁盘具有MBR分区表.在EFI系统上,W ...

  10. mysql 创建表单

    1.表名:Customer 属性: ID   字符型  最大10个字符   ——顾客编号 NAME   字符型  最大16个字符   ——顾客姓名 SEX     字符型  最大2个字符   ——性别 ...