从上一篇文章【温故知新】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的更多相关文章

  1. 事件EVENT与waitforsingleobject的使用

    事件event与waitforsingleobject的配合使用,能够解决很多同步问题,也可以在数据达到某个状态时启动另一个线程的执行,如报警. event的几个函数: 1.CreateEvent和O ...

  2. 经典线程同步 事件Event

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题 ...

  3. C#事件(event)解析

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

  4. 事件[event]_C#

    事件(event): 1.       事件是类在发生其关注的事情时用来提供通知的方式.例如,封装用户界面控件的类可以定义一个在单击该控件时发生的事件.控件类不关心单击按钮时发生了什么,但它需要告知派 ...

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

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

  6. MFC线程(三):线程同步事件(event)与互斥(mutex)

    前面讲了临界区可以用来达到线程同步.而事件(event)与互斥(mutex)也同样可以做到. Win32 API中的线程事件 HANDLE hEvent = NULL; void MainTestFu ...

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

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

  8. C#总结(二)事件Event 介绍总结

    最近在总结一些基础的东西,主要是学起来很难懂,但是在日常又有可能会经常用到的东西.前面介绍了 C# 的 AutoResetEvent的使用介绍, 这次介绍事件(event). 事件(event),对于 ...

  9. 多线程面试题系列(6):经典线程同步 事件Event

    上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的"线程所有权"特性所以关键段只能用于线程的互斥而不能用于同步.本篇介绍用事件Event来尝试解决这个线程同步问题.首先 ...

随机推荐

  1. nginx上如何支持.htaccess伪静态转向

    我们知道在apache上有一个常用的功能.htaccess转向,只要apache编译的时候指明支持rewrite模块就可以了. 但是换到nginx上方法会有一点不一样,网上很多人说把.htaccess ...

  2. html5.js

    可以让IE8等不支持Html5的浏览器,支持Html5元素,比如<header> <footer> <section>等标签 /* HTML5 Shiv v3.7. ...

  3. substring()、 substr() 、slice()的区别:

    stringObject.substring(start,stop) 用于提取字符串中介于两个指定下标之间的字符.start必需.一个非负的整数,规定要提取的子串的第一个字符在 stringObjec ...

  4. redis cluster安装部署(测试环境)

    redis 应用于web前端,做缓存和数据存取的速度是挺可观的,最近看了一些资料,手痒了,就弄了一个测试环境,两台方案,试用一下. ##Redis 集群部署## 一,方案调研: 参考博客: http: ...

  5. Python:异常处理

    Python 是面向对象的语言,所以程序抛出的异常也是类. 一.常见的异常类 NameError:尝试访问一个没有申明的变量 ZeroDivisionError:除数为 0 SyntaxError:语 ...

  6. √新技能Get - 教你发空白朋友圈

    今天下午都被空白朋友圈刷屏了.空白朋友圈也即是在朋友圈里面发空消息,没有图片也没有文字,朋友圈动态是空空的.这是谁在恶搞呢?怎么实现呢? 怎么发空消息啊?其实这是为了帮助大家识别身边用iOS的小伙伴的 ...

  7. 【译】Python中如何创建mock?

    原文地址:http://engineroom.trackmaven.com/blog/making-a-mockery-of-python/ 今天我们来谈论下mock的使用.当然,请不要误会,这里的m ...

  8. SGU 113

    113. Nearly prime numbers time limit per test: 0.25 sec. memory limit per test: 4096 KB Nearly prime ...

  9. iOS正则匹配手机号

    #pragma 正则匹配手机号 + (BOOL)validateMobile:(NSString *)mobileNum {     /**      * 手机号码      * 移动:134[0-8 ...

  10. HDU 1026 Ignatius and the Princess I (BFS)

    题目链接 题意 : 从(0,0)点走到(N-1,M-1)点,问最少时间. 思路 : BFS..... #include <stdio.h> #include <string.h> ...