【温故知新】c#事件event
从上一篇文章【温故知新】C#委托delegate可知,委托delegate和事件Event非常的相似,区别就是event关键字,给delegate穿上了个“马甲”。
让我们来看官方定义:
类或对象可以通过事件向其他类或对象通知发生的相关事情。 发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。
event 关键字用于在发行者类中声明事件。
定义非常明确,通过事件向其他类或对象通知发生的相关事情,用来实现的观察者模式。
还是通过之前的代码例子,看看声明delegate和event
//声明一个委托类型,通知家长
public delegate void NotifyDelegate(string msg); //老师被吩咐了1个委托
//声明委托:在发现早恋时时通知家长
private NotifyDelegate NotifyStudentLove; //声明事件,如果发现学生早恋! 就要通知那些订阅了这个事件的家长。
public event NotifyDelegate FindStudentLove;
让我们通过IL DASM来看看编译之后事件event的真正面目~
.event Delegate.Teacher/NotifyDelegate FindStudentLove
{
.addon instance void Delegate.Teacher::add_FindStudentLove(class Delegate.Teacher/NotifyDelegate)
.removeon instance void Delegate.Teacher::remove_FindStudentLove(class Delegate.Teacher/NotifyDelegate)
} // end of event Teacher::FindStudentLove
.method public hidebysig specialname instance void
add_FindStudentLove(class Delegate.Teacher/NotifyDelegate 'value') cil managed
{
// 代码大小 48 (0x30)
.maxstack
.locals init (class Delegate.Teacher/NotifyDelegate V_0,
class Delegate.Teacher/NotifyDelegate V_1,
class Delegate.Teacher/NotifyDelegate V_2,
bool V_3)
IL_0000: ldarg.
IL_0001: ldfld class Delegate.Teacher/NotifyDelegate Delegate.Teacher::FindStudentLove
IL_0006: stloc.
IL_0007: ldloc.
IL_0008: stloc.
IL_0009: ldloc.
IL_000a: ldarg.
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass Delegate.Teacher/NotifyDelegate
IL_0015: stloc.
IL_0016: ldarg.
IL_0017: ldflda class Delegate.Teacher/NotifyDelegate Delegate.Teacher::FindStudentLove
IL_001c: ldloc.
IL_001d: ldloc.
IL_001e: call !! [mscorlib]System.Threading.Interlocked::CompareExchange<class Delegate.Teacher/NotifyDelegate>(!!&,
!!,
!!)
IL_0023: stloc.
IL_0024: ldloc.
IL_0025: ldloc.
IL_0026: ceq
IL_0028: ldc.i4.
IL_0029: ceq
IL_002b: stloc.
IL_002c: ldloc.
IL_002d: brtrue.s IL_0007
IL_002f: ret
} // end of method Teacher::add_FindStudentLove
.method public hidebysig specialname instance void
remove_FindStudentLove(class Delegate.Teacher/NotifyDelegate 'value') cil managed
{
// 代码大小 48 (0x30)
.maxstack
.locals init (class Delegate.Teacher/NotifyDelegate V_0,
class Delegate.Teacher/NotifyDelegate V_1,
class Delegate.Teacher/NotifyDelegate V_2,
bool V_3)
IL_0000: ldarg.
IL_0001: ldfld class Delegate.Teacher/NotifyDelegate Delegate.Teacher::FindStudentLove
IL_0006: stloc.
IL_0007: ldloc.
IL_0008: stloc.
IL_0009: ldloc.
IL_000a: ldarg.
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_0010: castclass Delegate.Teacher/NotifyDelegate
IL_0015: stloc.
IL_0016: ldarg.
IL_0017: ldflda class Delegate.Teacher/NotifyDelegate Delegate.Teacher::FindStudentLove
IL_001c: ldloc.
IL_001d: ldloc.
IL_001e: call !! [mscorlib]System.Threading.Interlocked::CompareExchange<class Delegate.Teacher/NotifyDelegate>(!!&,
!!,
!!)
IL_0023: stloc.
IL_0024: ldloc.
IL_0025: ldloc.
IL_0026: ceq
IL_0028: ldc.i4.
IL_0029: ceq
IL_002b: stloc.
IL_002c: ldloc.
IL_002d: brtrue.s IL_0007
IL_002f: ret
} // end of method Teacher::remove_FindStudentLove
实际上编译器会帮你生成如下类似代码:
// 1. A PRIVATE delegate field that is initialized to null
private EventHandler<NewMailEventArgs> NewMail = null;
// 2. A PUBLIC add_Xxx method (where xxx is the Event name)
// Allows objects to register interest in the event.
[MethodImpl(MethodImplOptions.Synchronized)]
public void add_NewMail(EventHandler<NewMailEventArgs> value) {
NewMail = (EventHandler<NewMailEventArgs>)
Delegate.Combine(NewMail, value);
}
// 3. A PUBLIC remove_Xxx method (where Xxx is the Event name)
// Allows objects to unregister interest in the event.
[MethodImpl(MethodImplOptions.Synchronized)]
public void remove_NewMail(EventHandler<NewMailEventArgs> value) {
NewMail = (EventHandler<NewMailEventArgs>)
Delegate.Remove(NewMail, value);
}
当一个声明delegate前添加event之后,编译器为我们封装了delegate,这样,在之后的调用,就开放了+=,-=两个方法,这样极大保证了对象安全。
我们在使用c#内置事件的时候,总会发现EventHandler,EventArgs。这是因为.NET Framework为了规范,方便开发,已经为事件发布了准则。
.NET Framework 类库中的所有事件均基于 EventHandler 委托,定义如下:
public delegate void EventHandler(object sender, EventArgs e);
让我们把上一篇的代码改为符合.NET Framework事件准则
主场景:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace Delegate
{
class Program
{
static void Main(string[] args)
{
//家长A,B
Parent pa = new Parent();
Parent pb = new Parent(); //家长A,B分别委托老师发现早恋情况时通知他们
Teacher teacher = new Teacher();
teacher.FindStudentLove += pa.ReceiveMsg;
teacher.FindStudentLove += pb.ReceiveMsg; //老师开始检查早恋情况
teacher.CheckLove(); }
}
}
家长类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Delegate
{
public class Parent
{
/// <summary>
/// 接收消息
/// </summary>
/// <param name="msg">通知消息</param>
public void ReceiveMsg(object sender, StudentLoveEventArgs arg)
{
Console.WriteLine("家长收到通知:" + arg.Message);
}
}
}
老师类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Delegate
{
public class StudentLoveEventArgs : EventArgs
{
public StudentLoveEventArgs(string s)
{
message = s;
}
private string message; public string Message
{
get { return message; }
set { message = value; }
}
} public class Teacher
{ //声明一个委托类型,通知家长
public delegate void NotifyDelegate(string msg); //老师被吩咐了1个委托
//声明委托:在发现早恋时时通知家长
private NotifyDelegate NotifyStudentLove; //声明事件,如果发现学生早恋! 就要通知那些订阅了这个事件的家长。
public event EventHandler<StudentLoveEventArgs> FindStudentLove; //如果还想委托老师发现学生玩手机的时候通知一声,再声明一个委托即可
private NotifyDelegate NotifyStudentPlayMobile; //封装委托,使其符合面向对象,event关键字就为我们自动封装了。
public void add_NotifyStudentLove(NotifyDelegate newdelegate)
{
NotifyStudentLove += newdelegate;
} public void CheckLove()
{
//某一天AB同学突然发生纠纷!被老师发现啦!
string msg = "A同学和B同学早恋啦!!";
//检查是否有人委托老师办事
if (FindStudentLove != null)
{
//果断通知家长
FindStudentLove(this, new StudentLoveEventArgs(msg));
}
} }
}
【温故知新】c#事件event的更多相关文章
- 事件EVENT与waitforsingleobject的使用
事件event与waitforsingleobject的配合使用,能够解决很多同步问题,也可以在数据达到某个状态时启动另一个线程的执行,如报警. event的几个函数: 1.CreateEvent和O ...
- 经典线程同步 事件Event
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题 ...
- C#事件(event)解析
事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道windows消息处理机制的重要,其实C#事件就是基于window ...
- 事件[event]_C#
事件(event): 1. 事件是类在发生其关注的事情时用来提供通知的方式.例如,封装用户界面控件的类可以定义一个在单击该控件时发生的事件.控件类不关心单击按钮时发生了什么,但它需要告知派 ...
- C#中的委托(Delegate)和事件(Event)
原文地址:C#中的委托(Delegate)和事件(Event) 作者:jiyuan51 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写的设计模式--观察者(Obs ...
- MFC线程(三):线程同步事件(event)与互斥(mutex)
前面讲了临界区可以用来达到线程同步.而事件(event)与互斥(mutex)也同样可以做到. Win32 API中的线程事件 HANDLE hEvent = NULL; void MainTestFu ...
- 重温委托(delegate)和事件(event)
1.delegate是什么 某种意义上来讲,你可以把delegate理解成C语言中的函数指针,它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m,说白了就是可以把方法当作 ...
- C#总结(二)事件Event 介绍总结
最近在总结一些基础的东西,主要是学起来很难懂,但是在日常又有可能会经常用到的东西.前面介绍了 C# 的 AutoResetEvent的使用介绍, 这次介绍事件(event). 事件(event),对于 ...
- 多线程面试题系列(6):经典线程同步 事件Event
上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的"线程所有权"特性所以关键段只能用于线程的互斥而不能用于同步.本篇介绍用事件Event来尝试解决这个线程同步问题.首先 ...
随机推荐
- sublime 配置C++
1. 安装C语言编译器MinGW,并把MinGW安装目录下的bin目录添加到环境变量PATH里.详细方法参照MinGW安装和使用 2. 在SublimeText安装目录下的Data\Packages\ ...
- CSS 外边距(margin)重叠及防止方法
边界重叠是指两个或多个盒子(可能相邻也可能嵌套)的相邻边界(其间没有任何非空内容.补白.边框)重合在一起而形成一个单一边界. 两个或多个块级盒子的垂直相邻边界会重合.结果的边界宽度是相邻边界宽度中最大 ...
- IOS 提交审核,遇到Missing Push Notification Entitlement 问题。
貌似不影响提交........还是有人提交成了. 昨天晚上提交软件审核,遇到了Missing Push Notification Entitlement 的问题. 问题起因:这个版本我添加了PUSH推 ...
- Sqli-labs less 27a
Less-27a 本关与27关的区别在于对于id的处理,这里用的是 " ,同时mysql的错误不会在前端页面显示. 我们根据27关直接给出一个示例payload: http://127.0. ...
- 13test02:信用卡校验
/*#include<iostream> using namespace std; void input(); int counter=0,jishu_sum=0,oushu_sum=0, ...
- 使用 Swagger UI 与 Swashbuckle 创建 RESTful Web API 帮助文件
作者:Sreekanth Mothukuru 2016年2月18日 本文旨在介绍如何使用常用的 Swagger 和 Swashbuckle 框架创建描述 Restful API 的交互界面,并为 AP ...
- Simulate a seven-sided die using only five-sided
问题描述: 如题 转述一下问题,就是说你现在有一个正五面体骰子,然后你怎么用这个正五面体骰子去模拟一个正七面体骰子. 这个问题我接触到几种方法,下面一一阐述. 方法一: rand7()=( rand5 ...
- js正则表达式用法大全
匹配中文字符的正则表达式: [u4e00-u9fa5] 评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内):[^x00-xff] 评注:可以用来计算字符串的长度(一 ...
- spring_150803_component
实体类: package com.spring.model; public class DogPet { private int id; private String name; private in ...
- [转]linux CentOS 安装 Nginx
网上找的教程,一路走下来的,原文如下: 一.安装nginx 1.在nginx官方网站下载一个包,下载地址是:http://nginx.org/en/download.html 2.Wi ...