Overview

在前几章,我们已经对委托有了一个完整的了解了,本章将会对事件进行一下介绍:

相对于委托,事件再是我们更加频繁的接触的,比如 鼠标的click 事件,键盘的 keydown 事件等等。

事件的特点:

  • 只能进行 += 或者 -= 操作
  • 只能在,定义事件的类的内部调用事件,在其他类中不能调用

大家还记不记得学面向对象的时候,对属性是怎么描述的

对字段的封装,为了保护字段!

那么,事件之于委托,也是同样的目的, 对委托的封装,为了保护委托

我们在写代码的时候,一直会遵循这么一个规范: 永远不要经字段暴露出来! ,那么委托同样是这样能的,至于为什么这样,下文会有详细的介绍。

Event的语法

使用事件就要用到 event 关键字,并且事件是对委托的封装,有了委托才能有事件。

  1. 定义一个委托
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace UnderstandDelegate
{
public delegate void SimpleHandler();
}
  1. 将委托封装为事件
public event SimpleHandler SimpleEvent;

为什么要引入事件

为什么要引入属性的概念? 因为,将字段暴露出来不安全. 为什么引入事件,因为将委托暴露出来不安全。让我们来看一看为什么是这样。

  1. 定义一个委托
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace UnderstandDelegate
{
public delegate void SayHelloHandler();
}
  1. 建立一个Person类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace UnderstandDelegate
{
public class Person
{
public SayHelloHandler sayHelloHandler; public void SayHello()
{
if (sayHelloHandler != null)
sayHelloHandler.Invoke();
}
}
}
  1. 调用Person类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace UnderstandDelegate
{
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.sayHelloHandler += ChinaStyleSayHello;
person.sayHelloHandler += EnglishStyleSayHello;
} static void ChinaStyleSayHello()
{
Console.WriteLine("你好");
} static void EnglishStyleSayHello()
{
Console.WriteLine("Hello");
} static void JapanStyleSayHello()
{
Console.WriteLine("坑你急哇");
}
}
}

上面的代码,没有问题,是的确实是这样,如果没有意外的话。 请注意,我将犯一些致命的错误:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace UnderstandDelegate
{
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.sayHelloHandler += ChinaStyleSayHello;
person.sayHelloHandler += EnglishStyleSayHello;
//错误在这里,将之前赋值给委托的方法清空了
person.sayHelloHandler = null;
person.sayHelloHandler += JapanStyleSayHello;
} static void ChinaStyleSayHello()
{
Console.WriteLine("你好");
} static void EnglishStyleSayHello()
{
Console.WriteLine("Hello");
} static void JapanStyleSayHello()
{
Console.WriteLine("坑你急哇");
}
}
}

这还得了,如果说,因为你的一时疏忽,出现了上面的操作,如果说这个情况,是在一个大型的程序中,这种情况可是很致命的!

还有这种情况

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace UnderstandDelegate
{
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.sayHelloHandler += ChinaStyleSayHello;
person.sayHelloHandler += EnglishStyleSayHello;
//错误在这里,将之前赋值给委托的方法清空了
person.sayHelloHandler = null;
person.sayHelloHandler += JapanStyleSayHello;
//在Person类的外部,调用的Person类内部的委托
person.sayHelloHandler();
} static void ChinaStyleSayHello()
{
Console.WriteLine("你好");
} static void EnglishStyleSayHello()
{
Console.WriteLine("Hello");
} static void JapanStyleSayHello()
{
Console.WriteLine("坑你急哇");
}
}
}

这用情况,就更致命了,想象这么一个场景: 如果我们做了一个金融方面的项目,这项目中涉及到了资金的流转等敏感操作,恰恰这个操作,是交给一个委托来执行的,如果我们出现了这么一个情况,在不在调用的时候,自己手动调用了委托,那么,请做好老板找你谈话的准备吧。

这些问题都可以用事件来解决

我们需要对Person类,进行一下简单的修改。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace UnderstandDelegate
{
public class Person
{
//将委托封装为了事件
public event SayHelloHandler sayHelloHandler; public void SayHello()
{
if (sayHelloHandler != null)
sayHelloHandler.Invoke();
}
}
}

我们在看一下原来的代码

根本就不会被编译,那么这样就从根源上解决了我们使用委托,可能出现的高风险的问题。因为他根本就不让你编译,必须修改了才行![img](file:///C:\Users\IT\AppData\Local\Temp\SGPicFaceTpBq\19984\B10103B6.png)。

结语

可能,刚刚接触委托和事件的时候,刚刚回被这两个的概念搞得一脸懵逼,只需要记住: 事件是对委托的封装 即可。最后,希望本文可以帮助到各位看官。

文中有任何纰漏之处还望指出,以免笔者,误人误己,在此拜谢。

理解事件(Event)的更多相关文章

  1. 深入理解事件(Event)

    前言 在前一篇文章中讲到了Event 发布与订阅(一) 里面用到了事件来实现一些发布与订阅,当时对事件及其委托理解的还不是太深入,可能在使用上有点捉急.这篇来好好讲讲事件,以及通过一些小DEMO来加深 ...

  2. 深入理解事件(event)与委托(delegate)

    好久没学.NET了,最近重又开始学习,发现委托有很多变化了,发现事件不明白了(可能以前就没明白过) 网上搜索了几篇文章,也没注意什么时候的,发现都讲的不彻底,综合一下,也当个学习笔记. using S ...

  3. C#事件(event)解析

    事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道windows消息处理机制的重要,其实C#事件就是基于window ...

  4. C#中的委托(Delegate)和事件(Event)

    原文地址:C#中的委托(Delegate)和事件(Event) 作者:jiyuan51 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写的设计模式--观察者(Obs ...

  5. 重温委托(delegate)和事件(event)

    1.delegate是什么 某种意义上来讲,你可以把delegate理解成C语言中的函数指针,它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m,说白了就是可以把方法当作 ...

  6. Yii2基本概念之——事件(Event)

    说起事件(event),我们可是一点都不陌生.现实生活当中的事件无处不在,比如你发了一条微博,触发了一条事件,导致关注你的人收到了一条消息,看到你发的内容:比如你通过支付宝买东西,付了款,触发一个事件 ...

  7. {Python之线程} 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Threading模块 九 锁 十 信号量 十一 事件Event 十二 条件Condition(了解) 十三 定时器

    Python之线程 线程 本节目录 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Thr ...

  8. 详解 Solidity 事件Event - 完全搞懂事件的使用

    很多同学对Solidity 中的Event有疑问,这篇文章就来详细的看看Solidity 中Event到底有什么用? 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊. ...

  9. Spark2.1.0——深入理解事件总线

    Spark2.1.0——深入理解事件总线 概览 Spark程序在运行的过程中,Driver端的很多功能都依赖于事件的传递和处理,而事件总线在这中间发挥着至关重要的纽带作用.事件总线通过异步线程,提高了 ...

随机推荐

  1. id=%d是什么意思呢?

    $branch=M('Branchs')->where("id=%d",session('branchid'))->find(); %d代表,逗号后面那个user[]的 ...

  2. 【leetcode 简单】 第九十题 字符串中的第一个唯一字符

    给定一个字符串,找到它的第一个不重复的字符,并返回它的索引.如果不存在,则返回 -1. 案例: s = "leetcode" 返回 0. s = "loveleetcod ...

  3. 手动刷入Android 4.4.1 KOT49E OTA更新包

    一.Android 4.4 KitKat Google前段时间发布了Android新版本Android 4.4 KitKat,由于我的Nexus 4也是托朋友从US带回来的,所以很快就收到了Googl ...

  4. 利用正则表达式去除所有html标签,只保留文字

    后台将富文本编辑器中的内容返回到前端时如果带上了标签,这时就可以利用这种方法只保留文字. 标签的格式有以下几种 1.<div class="test"></div ...

  5. springcloud中eureka集群unavailable-replicas

    unavailable-replicas 配置了集群,但是在注册中心显示另外的几个集群地址是不可用的: 1 首先需要再host中添加服务名映射,如果应映射了再看是否在yml中配置了prefer-ip- ...

  6. Redis—数据结构之list

    Redis的列表对象底层所使用的数据结构其中之一就是list. list Redis的list是一个双端链表,其由3部分构成:链表节点.链表迭代器.链表.这一设计思想和STL的list是一样的,STL ...

  7. MySQL增量备份与恢复实例【转】

    小量的数据库可以每天进行完整备份,因为这也用不了多少时间,但当数据库很大时,就不太可能每天进行一次完整备份了,这时候就可以使用增量备份.增量备份的原理就是使用了mysql的binlog日志.本次操作的 ...

  8. Gradle设置代理

    在本地仓库路径下(如果没有修改的话默认C:\Users\用户名\.gradle),或者项目下,新建一个文件gradle.properties systemProp.http.proxyHost=网址 ...

  9. 10 The Go Programming Language Specification go语言规范 重点

    The Go Programming Language Specification go语言规范 Version of May 9, 2018 Introduction 介绍 Notation 符号 ...

  10. 06 Frequently Asked Questions (FAQ) 常见问题解答 (常见问题)

    Frequently Asked Questions (FAQ) Origins 起源 What is the purpose of the project? What is the history ...