浅谈C#事件
一、基本介绍
事件是一种特殊的多播委托,用于实现发布-订阅模式。事件允许对象在发生特定情况时通知其他对象。事件的发布者(也称为事件源)定义事件,并在适当的时机触发事件;事件的订阅者(也称为事件处理程序)订阅事件,并在事件被触发时接收通知。
事件的基本使用
定义事件:在类中定义一个事件,通常使用 event
关键字。
public class Publisher
{
// 定义一个事件
public event EventHandler MyEvent;
// 触发事件的方法
protected virtual void OnMyEvent(EventArgs e)
{
MyEvent?.Invoke(this, e);
}
// 调用该方法来触发事件
public void DoSomething()
{
// 执行某些操作...
OnMyEvent(EventArgs.Empty);
}
}
订阅事件:在另一个类中订阅事件。
public class Subscriber
{
public void Subscribe(Publisher publisher)
{
publisher.MyEvent += OnPublisherEvent;
}
private void OnPublisherEvent(object sender, EventArgs e)
{
Console.WriteLine("Publisher raised an event!");
}
}
取消订阅事件:如果不再需要接收事件通知,可以取消订阅。
public void Unsubscribe(Publisher publisher)
{
publisher.MyEvent -= OnPublisherEvent;
}
事件的触发
事件本身不是方法,而是一种特殊的多播委托。在类内部,通常会有一个受保护的方法来触发事件,这个方法会调用事件委托。使用 ?.
操作符可以确保在事件没有订阅者时不会引发空引用异常。
事件的安全性
- 线程安全:在多线程环境中,事件的触发应该考虑线程安全。可以使用
lock
语句来同步对事件委托的访问。 - 避免空引用异常:使用
?.Invoke
来避免在没有订阅者时引发空引用异常。
事件的高级特性
- 自定义事件参数:可以定义自定义的事件参数类来传递更复杂的数据。
- 弱事件模式:为了减少内存泄漏的风险,可以使用弱事件模式。在这种模式下,事件订阅者持有事件源的弱引用。
示例:使用自定义事件参数
public class Publisher
{
public event EventHandler<MyEventArgs> MyEvent;
protected virtual void OnMyEvent(MyEventArgs e)
{
MyEvent?.Invoke(this, e);
}
public void DoSomething(string message)
{
OnMyEvent(new MyEventArgs { Message = message });
}
}
public class MyEventArgs : EventArgs
{
public string Message { get; set; }
}
public class Subscriber
{
public void Subscribe(Publisher publisher)
{
publisher.MyEvent += OnPublisherEvent;
}
private void OnPublisherEvent(object sender, MyEventArgs e)
{
Console.WriteLine($"Publisher raised an event with message: {e.Message}");
}
}
在这个示例中,MyEventArgs
是一个自定义的事件参数类,它允许事件处理程序接收额外的信息。事件的发布者在触发事件时创建并传递这个自定义事件参数的实例。