CSharp中使用interface(接口)还是delegate(委托)+event(事件)

前言

在 C# 中,interface(接口)和 delegate + event(委托 + 事件)都是实现类型间交互的重要机制,但它们的设计目标和适用场景不同。

选择哪一种取决于具体需求,以下是两者的核心区别和适用场景分析:

维度 接口(Interface) 委托 + 事件(Delegate + Event)
交互方式 主动调用(调用方直接调用接口方法) 被动通知(发布者触发事件,订阅者响应)
耦合度 相对紧密(调用方依赖接口,实现方必须实现契约) 松耦合(发布者和订阅者互不依赖具体类型)
成员数量 可包含多个方法、属性、事件等 通常对应单一方法签名(委托定义的签名)
灵活性 契约固定,实现后不易动态变更 可动态订阅 / 取消订阅,适应变化
典型用途 定义功能契约、多态交互 实现事件通知、回调机制

如何选择?

  • 用接口:当需要定义 “必须实现的功能契约”,且调用方需要主动触发这些功能时(如 “所有日志器必须实现写日志方法”)。
  • 用委托 + 事件:当需要 “某个事件发生时通知其他对象”,且发布者无需知道谁会响应时(如 “用户点击按钮时,通知所有注册的处理逻辑”)。

混合使用场景:实际开发中两者常结合使用。例如,接口中可以包含事件成员(如 INotifyPropertyChanged 接口定义了 PropertyChanged 事件),既规范了契约,又利用事件实现通知。

interface(接口)

interface 适合事件只被一个订阅者处理,并且需要实现所有的接口。

接口

1
2
3
4
5
6
7
8
public interface IPenEvent
{
void PenDown(double xRate, double yRate);

void PenMove(double xRate, double yRate);

void PenUp();
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ZPenUtils
{
public IPenEvent penEvent;
public static ZPenUtils instance;
public static ZPenUtils GetInstance()
{
return instance ?? (instance = new ZPenUtils());
}

public void PenUp()
{
penEvent?.PenUp();
}

public void PenDown(double xRate, double yRate)
{
penEvent?.PenDown(xRate, yRate);
}

public void PenMove(double xRate, double yRate)
{
penEvent?.PenMove(xRate, yRate);
}
}

delegate(委托)+event(事件)

使用 委托 + 事件 可以实现一个事件被多个地方(订阅者)同时接收和处理,这正是事件模型的核心优势之一。

委托

1
public delegate void OnLineStatus(int nIndex, bool bOnLine);

事件

1
public event OnLineStatus onLineEvent;