在C#中,委托(Delegate)和事件(Event)是两种强大的机制,它们都与方法的引用有关,但它们的用途和语义有所不同。
下面是一个C#代码示例,它展示了委托和事件的使用,并解释了它们之间的区别。
using System;
// 定义一个委托,它指定了一个没有参数并且没有返回值的方法的类型
public delegate void DisplayMessage();
// 定义一个类,它包含了一个事件和一个触发该事件的方法
class MessagePublisher
{
// 定义一个事件,它使用了上面定义的委托类型
public event DisplayMessage OnDisplay;
// 定义一个方法,用于触发事件
public void PublishMessage()
{
Console.WriteLine("messagepublisher:事件即将被触发。");
// 触发事件
OnDisplay?.Invoke();
}
}
// 定义一个类,它包含了一个方法,该方法与委托签名匹配,因此可以订阅事件
class MessageSubscriber
{
// 定义一个方法,该方法与委托签名匹配
public void Display()
{
Console.WriteLine("MessageSubscriber:已调用DisplayMessage。");
}
}
class Program
{
static void Main()
{
// 创建消息发布者的实例
MessagePublisher publisher = new MessagePublisher();
// 创建消息订阅者的实例
MessageSubscriber subscriber = new MessageSubscriber();
// 订阅事件
publisher.OnDisplay += subscriber.Display;
// 触发事件
publisher.PublishMessage();
// 取消订阅事件
publisher.OnDisplay -= subscriber.Display;
// 再次触发事件,这次不会有任何输出,因为事件已经取消订阅
publisher.PublishMessage();
}
}
-
DisplayMessage
是一个委托类型,它定义了方法的签名,即没有参数和返回值。 -
MessagePublisher
类包含了一个名为OnDisplay
的事件。这个事件使用了DisplayMessage
委托类型。 -
PublishMessage
方法用于触发OnDisplay
事件。在这个方法中,我们使用?.Invoke()
语法来调用委托,这是C# 6.0引入的空条件操作符,它确保在事件有订阅者时才调用。 -
MessageSubscriber
类包含了一个名为Display
的方法,它与DisplayMessage
委托的签名匹配。 -
在
Main
方法中,我们创建了MessagePublisher
和MessageSubscriber
的实例。 -
通过
publisher.OnDisplay += subscriber.Display;
这行代码,我们将MessageSubscriber
的Display
方法订阅到MessagePublisher
的OnDisplay
事件上。 -
当调用
publisher.PublishMessage();
时,它触发了OnDisplay
事件,导致MessageSubscriber
的Display
方法被调用。 -
通过
publisher.OnDisplay -= subscriber.Display;
这行代码,我们取消了Display
方法的订阅。 -
最后再次调用
publisher.PublishMessage();
,这次不会有输出,因为事件已经被取消订阅了。
委托与事件的区别:
-
委托:是一种类型,可以持有方法的引用。委托可以实例化,并且可以指向一个或多个方法。委托是多播的,可以附加多个方法。
-
事件:是基于委托的一种特殊用途的机制,用于实现发布-订阅模式。事件通常作为类或对象的成员,并且其访问受到限制,只能在声明事件的类内部添加或移除事件处理程序。
-
在这个例子中,
OnDisplay
是一个事件,它使用了DisplayMessage
委托类型。事件提供了一种安全的方式来订阅和取消订阅,而委托则提供了一种灵活的方式来引用和调用方法。