C#
和Java
比较:
Java
中使用的是接口。C#
使用委托机制,可以用时+
运算符进行注册,直接多播。而Java
中是一般是使用一个集合来保存观察者。
发布者Publisher
= 被观察者Observable
= 事件源(Java
中的EventObject
,C#
中的sender
)
订阅者Subscriber
= 观察者Observer
= 接收者(Java
中继承EventLister
、接口或Observer
接口, C#
由于委托机制,不需要继承接口,直接按EventHandler
实现回调方法)
在发生其他类或对象关注的事情时,类或对象可通过事件通知它们。发送(或引发)事件的类称为【发布者】,接收(或处理)事件的类称为【订阅者】。
在典型的 C# Windows
窗体或Web
应用程序中,可订阅由控件(如按钮和列表框)引发的事件。可使用 C#
集成开发环境 IDE
来浏览控件发布的事件,选择要处理的事件。IDE
会自动添加空事件处理程序方法和订阅事件的代码。
EventHandler
为C#
中的预定义委托,专用于表示不生成数据的事件的处理程序方法。
public delegate void EventHandler(Object sender, EventArgs e)
事件具有以下特点:
- 发布者确定何时引发事件,订阅者确定执行何种操作来响应该事件。
- 一个事件可以有多个订阅者。一个订阅者可处理来自多个发布者的多个事件。
- 没有订阅者的事件永远不会被调用。
- 事件通常用于通知用户操作(如:图形用户界面中的按钮单击或菜单选择操作)。
- 如果一个事件有多个订阅者,当引发该事件时,会同步调用多个事件处理程序。要异步调用事件,请参见使用异步方式调用同步方法。
- 可以利用事件同步线程。
- 在
.NET Framework
类库中,事件是基于EventHandler
委托和EventArgs
基类的。
示例代码:
下面的示例演示了上述步骤,它将自定义EventArgs
类和 EventHandler<T>
用作事件类型。
namespace ConsoleApplication2
{
using System;
using System.Collections.Generic;
// 自定义一个事件类来保存事件信息
public class CustomEventArgs : EventArgs
{
public CustomEventArgs(string s)
{
message = s;
}
private string message;
public string Message
{
get { return message; }
set { message = value; }
}
}
// 广播事件的类
class Publisher
{
// 使用 EventHandler<T> 声明一个事件
public event EventHandler<CustomEventArgs> RaiseCustomEvent;
//这个方法是做了一些事情,然后触发一个事件
public void DoSomething()
{
// DoSomething....
// 你也可以再触发事件前,执行一些其他的代码
OnRaiseCustomEvent(new CustomEventArgs("Did something,hi 这是事件消息"));
}
//使用虚方法让派生类可以重写
protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
{
// 定义一个局部变量,已防止最后一个订阅者刚好在检查null后取消订阅
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
// 如果没有订阅者(观察者),委托对象将为null
if (handler != null)
{
// 格式化事件消息中的字符串
e.Message += String.Format(" at {0}", DateTime.Now.ToString());
// 这是最重要的一句。
// 此时执行的handler已经是一个多播委托(如果有多个订阅者或观察者注册)。
// 既然是多播委托,就可以依次调用各个回调函数 (既然是回调函数,实际的执行就由订阅者类决定)。
// 这里面传入一个this, 就代表事件源(发布者或被观察者)
handler(this, e);
}
}
}
//用来注册事件的类
class Subscriber
{
private string id;
public Subscriber(string ID, Publisher pub)
{
id = ID;//注册这个动作,应该有订阅者主动进行,并且可以再后期取消注册
pub.RaiseCustomEvent += HandleCustomEvent;
}
// 实现回调函数。在事件发生后,执行什么样的操作。这里只是简单的打印信息。
void HandleCustomEvent(object sender, CustomEventArgs e)
{
//这就是实际的操作。
Console.WriteLine(id + " received this message: {0}", e.Message);
}
}
class Class1
{
static void Main(string[] args)
{
Publisher pub = new Publisher();
Subscriber sub1 = new Subscriber("sub1", pub);
Subscriber sub2 = new Subscriber("sub2", pub);
pub.DoSomething(); // 调用这个方法来产生事件
Console.WriteLine("Press Enter to close this window.");
Console.ReadLine();
}
}
}