您的位置:首页 > 编程语言 > C#

CLR Via C# 3rd 阅读摘要 -- Chapter 11 - Events

2010-04-06 16:55 501 查看

Designing a Type That Exposes an Event

Step #1:定义一个类型用来持有将要发送给事件通知接受者的额外信息。从System.EventArgs继承,EventArgs.Empty;

Setp #2:定义一个事件成员;

public event EventHandler<NewMailEventArgs> NewMail;

Step #3:定义一个方法引发事件以通知注册的对象事件以及发生;

protected virtual void OnNewMail(NewMailEventArgs e) {

EventHandler<NewMailEventArgs> temp = Interlocked.CompareExchange(ref NewMail, null, null);

if (temp != null) temp(this, e);

}

如何线程安全的引发事件?

1. 下面这段代码的temp可能会被编译器优化掉;

EventHandler<NewMailEventArgs> temp = NewMail;

if (temp != null) temp(this, e);

2. 下面这段代码是臆想,因为VolatileRead没有一个泛型的重载;

EventHandler<NewMailEventArgs> temp = Thread.VolatileRead(re NewMail);

...

3. 最后一种方法就是Step #2中的那段,但是实际应用时用1.的代码也可行。总之要注意线程的竞争条件。

Step #4:定义一个方法将输入转化到期望的事件;

public void Xyz(...) {

...

NewMailEventArgs e = new NewMailEventArgs(from ,to, subject);

OnNewMail(e);

...

}

How the Complier Implements an Event

1. 一个PRIVATE的初始化成null的委托字段;

private EventHandler<NewMailEventArgs> NewMail = null;

2. 一个PUBLIC的add_Xyz的方法(Xyz就是事件名字)。Delegate.Combine;

public void add_NewMail(EventHandler<NewMailEventArgs> value)

3. 一个PUBLIC的remove_Xyz的方法。Delegate.Remove;

public void remove_NewMail(EventHandler<NewMailEventArgs> value)

注意:

Delegate.Remove一个从未Add过的方法时,啥也不做,并不会抛出异常啥的。
Delegate.Add和Remove采用Interlocked Anything模式来保证线程安全。
事件成员可以定义成static和virtual的。

Designing a Type That Listens for an Event

1. C#要求你使用+=和-=操作符在列表中add和remove委托。如果显示的调用add和remove方法,编译器会报错:CS0571。

Explicitly Implementing an Event

1. 使用一个字典存储事件标示符(键)和委托链(值);

2. System.ComponentModel.EventHandlerList。

本章小结

CLR的事件模型是基于委托的,是一种特殊的委托,委托就是类型安全的回调函数。描述了如何在类型中暴露事件的步骤以及如何侦听事件,对比了如何安全的触发事件的不同方式。然后分析了编译器如何编译事件。 最后设计了一个EventSet来显示的实现事件以节约资源。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: